From 9c63abc9a1d127f95162756467284cf76b47aff8 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 7 Dec 2011 01:11:29 +0000 Subject: libgo: Update to weekly 2011-11-09. From-SVN: r182073 --- libgo/go/archive/tar/reader.go | 4 +- libgo/go/archive/zip/reader.go | 3 +- libgo/go/archive/zip/reader_test.go | 6 +- libgo/go/archive/zip/writer_test.go | 2 +- libgo/go/asn1/asn1.go | 841 ---------- libgo/go/asn1/asn1_test.go | 689 -------- libgo/go/asn1/common.go | 158 -- libgo/go/asn1/marshal.go | 547 ------- libgo/go/asn1/marshal_test.go | 129 -- libgo/go/big/arith.go | 242 --- libgo/go/big/arith_decl.go | 18 - libgo/go/big/arith_test.go | 335 ---- libgo/go/big/calibrate_test.go | 88 - libgo/go/big/hilbert_test.go | 160 -- libgo/go/big/int.go | 873 ---------- libgo/go/big/int_test.go | 1403 ---------------- libgo/go/big/nat.go | 1271 --------------- libgo/go/big/nat_test.go | 669 -------- libgo/go/big/rat.go | 432 ----- libgo/go/big/rat_test.go | 456 ------ libgo/go/bufio/bufio.go | 13 +- libgo/go/bufio/bufio_test.go | 13 +- libgo/go/builtin/builtin.go | 92 +- libgo/go/bytes/buffer.go | 14 +- libgo/go/bytes/buffer_test.go | 4 +- libgo/go/bytes/bytes.go | 7 +- libgo/go/bytes/bytes_test.go | 2 +- libgo/go/cmath/abs.go | 12 - libgo/go/cmath/asin.go | 170 -- libgo/go/cmath/cmath_test.go | 853 ---------- libgo/go/cmath/conj.go | 8 - libgo/go/cmath/exp.go | 55 - libgo/go/cmath/isinf.go | 21 - libgo/go/cmath/isnan.go | 25 - libgo/go/cmath/log.go | 64 - libgo/go/cmath/phase.go | 11 - libgo/go/cmath/polar.go | 12 - libgo/go/cmath/pow.go | 60 - libgo/go/cmath/rect.go | 13 - libgo/go/cmath/sin.go | 132 -- libgo/go/cmath/sqrt.go | 103 -- libgo/go/cmath/tan.go | 184 --- libgo/go/compress/bzip2/bit_reader.go | 4 +- libgo/go/compress/bzip2/bzip2.go | 4 +- libgo/go/compress/zlib/testdata/e.txt | 1 - libgo/go/compress/zlib/testdata/pi.txt | 1 - libgo/go/container/heap/heap.go | 9 +- libgo/go/container/heap/heap_test.go | 2 +- libgo/go/crypto/dsa/dsa.go | 2 +- libgo/go/crypto/dsa/dsa_test.go | 2 +- libgo/go/crypto/ecdsa/ecdsa.go | 2 +- libgo/go/crypto/ecdsa/ecdsa_test.go | 4 +- libgo/go/crypto/elliptic/elliptic.go | 2 +- libgo/go/crypto/elliptic/elliptic_test.go | 2 +- libgo/go/crypto/hmac/hmac_test.go | 2 +- libgo/go/crypto/ocsp/ocsp.go | 2 +- libgo/go/crypto/openpgp/armor/armor.go | 2 +- libgo/go/crypto/openpgp/elgamal/elgamal.go | 2 +- libgo/go/crypto/openpgp/elgamal/elgamal_test.go | 2 +- libgo/go/crypto/openpgp/packet/encrypted_key.go | 2 +- .../go/crypto/openpgp/packet/encrypted_key_test.go | 2 +- libgo/go/crypto/openpgp/packet/packet.go | 2 +- libgo/go/crypto/openpgp/packet/private_key.go | 2 +- libgo/go/crypto/openpgp/packet/public_key.go | 2 +- libgo/go/crypto/openpgp/s2k/s2k_test.go | 2 +- libgo/go/crypto/rand/util.go | 2 +- libgo/go/crypto/rsa/pkcs1v15.go | 2 +- libgo/go/crypto/rsa/pkcs1v15_test.go | 2 +- libgo/go/crypto/rsa/rsa.go | 2 +- libgo/go/crypto/rsa/rsa_test.go | 2 +- libgo/go/crypto/tls/conn.go | 2 +- libgo/go/crypto/tls/generate_cert.go | 4 +- libgo/go/crypto/tls/handshake_messages_test.go | 2 +- libgo/go/crypto/tls/handshake_server_test.go | 2 +- libgo/go/crypto/tls/key_agreement.go | 2 +- libgo/go/crypto/x509/pkcs1.go | 6 +- libgo/go/crypto/x509/pkix/pkix.go | 4 +- libgo/go/crypto/x509/x509.go | 4 +- libgo/go/crypto/x509/x509_test.go | 4 +- libgo/go/csv/reader.go | 372 ----- libgo/go/csv/reader_test.go | 281 ---- libgo/go/csv/writer.go | 121 -- libgo/go/csv/writer_test.go | 44 - libgo/go/debug/gosym/pclntab_test.go | 2 +- libgo/go/encoding/asn1/asn1.go | 841 ++++++++++ libgo/go/encoding/asn1/asn1_test.go | 689 ++++++++ libgo/go/encoding/asn1/common.go | 158 ++ libgo/go/encoding/asn1/marshal.go | 547 +++++++ libgo/go/encoding/asn1/marshal_test.go | 129 ++ libgo/go/encoding/binary/binary.go | 2 +- libgo/go/encoding/binary/binary_test.go | 1 - libgo/go/encoding/csv/reader.go | 372 +++++ libgo/go/encoding/csv/reader_test.go | 281 ++++ libgo/go/encoding/csv/writer.go | 121 ++ libgo/go/encoding/csv/writer_test.go | 44 + libgo/go/encoding/gob/codec_test.go | 1406 ++++++++++++++++ libgo/go/encoding/gob/debug.go | 687 ++++++++ libgo/go/encoding/gob/decode.go | 1279 +++++++++++++++ libgo/go/encoding/gob/decoder.go | 214 +++ libgo/go/encoding/gob/doc.go | 366 +++++ libgo/go/encoding/gob/dump.go | 22 + libgo/go/encoding/gob/encode.go | 717 +++++++++ libgo/go/encoding/gob/encoder.go | 251 +++ libgo/go/encoding/gob/encoder_test.go | 664 ++++++++ libgo/go/encoding/gob/error.go | 39 + libgo/go/encoding/gob/gobencdec_test.go | 528 ++++++ libgo/go/encoding/gob/timing_test.go | 94 ++ libgo/go/encoding/gob/type.go | 788 +++++++++ libgo/go/encoding/gob/type_test.go | 161 ++ libgo/go/encoding/json/decode.go | 939 +++++++++++ libgo/go/encoding/json/decode_test.go | 564 +++++++ libgo/go/encoding/json/encode.go | 472 ++++++ libgo/go/encoding/json/encode_test.go | 84 + libgo/go/encoding/json/indent.go | 114 ++ libgo/go/encoding/json/scanner.go | 621 +++++++ libgo/go/encoding/json/scanner_test.go | 302 ++++ libgo/go/encoding/json/stream.go | 185 +++ libgo/go/encoding/json/stream_test.go | 147 ++ libgo/go/encoding/json/tagkey_test.go | 95 ++ libgo/go/encoding/json/tags.go | 44 + libgo/go/encoding/json/tags_test.go | 28 + libgo/go/encoding/xml/atom_test.go | 50 + libgo/go/encoding/xml/embed_test.go | 124 ++ libgo/go/encoding/xml/marshal.go | 304 ++++ libgo/go/encoding/xml/marshal_test.go | 423 +++++ libgo/go/encoding/xml/read.go | 630 ++++++++ libgo/go/encoding/xml/read_test.go | 402 +++++ libgo/go/encoding/xml/xml.go | 1697 ++++++++++++++++++++ libgo/go/encoding/xml/xml_test.go | 609 +++++++ libgo/go/exec/exec.go | 393 ----- libgo/go/exec/exec_test.go | 257 --- libgo/go/exec/lp_plan9.go | 52 - libgo/go/exec/lp_test.go | 33 - libgo/go/exec/lp_unix.go | 55 - libgo/go/exec/lp_windows.go | 78 - libgo/go/exp/ebnf/ebnf.go | 4 +- libgo/go/exp/ebnf/parser.go | 2 +- libgo/go/exp/norm/composition.go | 2 +- libgo/go/exp/norm/input.go | 2 +- libgo/go/exp/norm/maketables.go | 2 +- libgo/go/exp/norm/normalize.go | 2 +- libgo/go/exp/norm/normregtest.go | 4 +- libgo/go/exp/norm/trie_test.go | 2 +- libgo/go/exp/norm/triegen.go | 2 +- libgo/go/exp/spdy/read.go | 2 +- libgo/go/exp/spdy/spdy_test.go | 2 +- libgo/go/exp/spdy/types.go | 2 +- libgo/go/exp/spdy/write.go | 2 +- libgo/go/exp/sql/convert.go | 71 +- libgo/go/exp/sql/convert_test.go | 52 + libgo/go/exp/sql/driver/driver.go | 14 +- libgo/go/exp/sql/driver/types.go | 62 +- libgo/go/exp/sql/driver/types_test.go | 57 + libgo/go/exp/sql/fakedb_test.go | 2 +- libgo/go/exp/sql/sql.go | 264 ++- libgo/go/exp/ssh/client.go | 57 +- libgo/go/exp/ssh/client_auth.go | 157 ++ libgo/go/exp/ssh/common.go | 2 +- libgo/go/exp/ssh/doc.go | 2 +- libgo/go/exp/ssh/messages.go | 2 +- libgo/go/exp/ssh/messages_test.go | 4 +- libgo/go/exp/ssh/server.go | 2 +- libgo/go/exp/template/html/attr.go | 175 -- libgo/go/exp/template/html/clone.go | 90 -- libgo/go/exp/template/html/clone_test.go | 90 -- libgo/go/exp/template/html/content.go | 94 -- libgo/go/exp/template/html/content_test.go | 222 --- libgo/go/exp/template/html/context.go | 339 ---- libgo/go/exp/template/html/css.go | 268 ---- libgo/go/exp/template/html/css_test.go | 281 ---- libgo/go/exp/template/html/doc.go | 190 --- libgo/go/exp/template/html/error.go | 213 --- libgo/go/exp/template/html/escape.go | 760 --------- libgo/go/exp/template/html/escape_test.go | 1622 ------------------- libgo/go/exp/template/html/html.go | 257 --- libgo/go/exp/template/html/html_test.go | 94 -- libgo/go/exp/template/html/js.go | 346 ---- libgo/go/exp/template/html/js_test.go | 401 ----- libgo/go/exp/template/html/transition.go | 553 ------- libgo/go/exp/template/html/url.go | 105 -- libgo/go/exp/template/html/url_test.go | 112 -- libgo/go/exp/types/const.go | 4 +- libgo/go/exp/types/gcimporter.go | 4 +- libgo/go/exp/types/gcimporter_test.go | 2 +- libgo/go/exp/wingui/gui.go | 2 +- libgo/go/exp/wingui/winapi.go | 2 +- libgo/go/expvar/expvar.go | 4 +- libgo/go/expvar/expvar_test.go | 2 +- libgo/go/fmt/format.go | 2 +- libgo/go/fmt/print.go | 2 +- libgo/go/fmt/scan.go | 4 +- libgo/go/fmt/scan_test.go | 2 +- libgo/go/go/ast/ast.go | 2 +- libgo/go/go/ast/import.go | 139 ++ libgo/go/go/build/build.go | 2 +- libgo/go/go/build/build_test.go | 2 +- libgo/go/go/doc/comment.go | 2 +- libgo/go/go/doc/example.go | 2 +- libgo/go/go/parser/parser.go | 2 +- libgo/go/go/printer/printer.go | 2 +- libgo/go/go/scanner/scanner.go | 2 +- libgo/go/go/token/serialize.go | 2 +- libgo/go/gob/codec_test.go | 1406 ---------------- libgo/go/gob/decode.go | 1279 --------------- libgo/go/gob/decoder.go | 214 --- libgo/go/gob/doc.go | 366 ----- libgo/go/gob/encode.go | 717 --------- libgo/go/gob/encoder.go | 251 --- libgo/go/gob/encoder_test.go | 664 -------- libgo/go/gob/error.go | 39 - libgo/go/gob/gobencdec_test.go | 528 ------ libgo/go/gob/timing_test.go | 94 -- libgo/go/gob/type.go | 787 --------- libgo/go/gob/type_test.go | 153 -- libgo/go/html/doc.go | 4 +- libgo/go/html/entity_test.go | 2 +- libgo/go/html/escape.go | 2 +- libgo/go/html/parse.go | 68 +- libgo/go/html/parse_test.go | 40 +- libgo/go/html/template/attr.go | 175 ++ libgo/go/html/template/clone.go | 90 ++ libgo/go/html/template/clone_test.go | 90 ++ libgo/go/html/template/content.go | 94 ++ libgo/go/html/template/content_test.go | 221 +++ libgo/go/html/template/context.go | 339 ++++ libgo/go/html/template/css.go | 268 ++++ libgo/go/html/template/css_test.go | 281 ++++ libgo/go/html/template/doc.go | 186 +++ libgo/go/html/template/error.go | 197 +++ libgo/go/html/template/escape.go | 752 +++++++++ libgo/go/html/template/escape_test.go | 1616 +++++++++++++++++++ libgo/go/html/template/html.go | 257 +++ libgo/go/html/template/html_test.go | 94 ++ libgo/go/html/template/js.go | 346 ++++ libgo/go/html/template/js_test.go | 401 +++++ libgo/go/html/template/template.go | 239 +++ libgo/go/html/template/transition.go | 553 +++++++ libgo/go/html/template/url.go | 105 ++ libgo/go/html/template/url_test.go | 112 ++ .../pending-spec-changes-plain-text-unsafe.dat | Bin 0 -> 115 bytes libgo/go/html/token.go | 8 +- libgo/go/html/token_test.go | 10 +- libgo/go/http/cgi/child.go | 192 --- libgo/go/http/cgi/child_test.go | 87 - libgo/go/http/cgi/host.go | 350 ---- libgo/go/http/cgi/host_test.go | 482 ------ libgo/go/http/cgi/matryoshka_test.go | 74 - libgo/go/http/cgi/testdata/test.cgi | 96 -- libgo/go/http/chunked.go | 76 - libgo/go/http/client.go | 304 ---- libgo/go/http/client_test.go | 318 ---- libgo/go/http/cookie.go | 267 --- libgo/go/http/cookie_test.go | 200 --- libgo/go/http/doc.go | 79 - libgo/go/http/dump.go | 77 - libgo/go/http/export_test.go | 41 - libgo/go/http/fcgi/child.go | 258 --- libgo/go/http/fcgi/fcgi.go | 271 ---- libgo/go/http/fcgi/fcgi_test.go | 113 -- libgo/go/http/filetransport.go | 123 -- libgo/go/http/filetransport_test.go | 62 - libgo/go/http/fs.go | 324 ---- libgo/go/http/fs_test.go | 308 ---- libgo/go/http/header.go | 78 - libgo/go/http/header_test.go | 81 - libgo/go/http/httptest/recorder.go | 58 - libgo/go/http/httptest/server.go | 177 -- libgo/go/http/lex.go | 144 -- libgo/go/http/lex_test.go | 70 - libgo/go/http/persist.go | 421 ----- libgo/go/http/pprof/pprof.go | 133 -- libgo/go/http/proxy_test.go | 48 - libgo/go/http/range_test.go | 57 - libgo/go/http/readrequest_test.go | 180 --- libgo/go/http/request.go | 863 ---------- libgo/go/http/request_test.go | 285 ---- libgo/go/http/requestwrite_test.go | 470 ------ libgo/go/http/response.go | 236 --- libgo/go/http/response_test.go | 446 ----- libgo/go/http/responsewrite_test.go | 109 -- libgo/go/http/reverseproxy.go | 171 -- libgo/go/http/reverseproxy_test.go | 71 - libgo/go/http/serve_test.go | 1154 ------------- libgo/go/http/server.go | 1189 -------------- libgo/go/http/sniff.go | 214 --- libgo/go/http/sniff_test.go | 80 - libgo/go/http/status.go | 106 -- libgo/go/http/testdata/file | 1 - libgo/go/http/testdata/index.html | 1 - libgo/go/http/testdata/style.css | 1 - libgo/go/http/transfer.go | 571 ------- libgo/go/http/transport.go | 744 --------- libgo/go/http/transport_test.go | 639 -------- libgo/go/http/transport_windows.go | 21 - libgo/go/image/bmp/reader.go | 2 +- libgo/go/image/jpeg/writer_test.go | 2 +- libgo/go/index/suffixarray/suffixarray_test.go | 2 +- libgo/go/io/multi_test.go | 2 +- libgo/go/json/decode.go | 939 ----------- libgo/go/json/decode_test.go | 564 ------- libgo/go/json/encode.go | 472 ------ libgo/go/json/encode_test.go | 84 - libgo/go/json/indent.go | 114 -- libgo/go/json/scanner.go | 621 ------- libgo/go/json/scanner_test.go | 302 ---- libgo/go/json/stream.go | 185 --- libgo/go/json/stream_test.go | 147 -- libgo/go/json/tagkey_test.go | 95 -- libgo/go/json/tags.go | 44 - libgo/go/json/tags_test.go | 28 - libgo/go/log/log.go | 4 +- libgo/go/log/syslog/syslog.go | 149 ++ libgo/go/log/syslog/syslog_c.c | 19 + libgo/go/log/syslog/syslog_libc.go | 36 + libgo/go/log/syslog/syslog_test.go | 113 ++ libgo/go/log/syslog/syslog_unix.go | 31 + libgo/go/mail/message.go | 524 ------ libgo/go/mail/message_test.go | 277 ---- libgo/go/math/all_test.go | 72 +- libgo/go/math/big/arith.go | 242 +++ libgo/go/math/big/arith_decl.go | 18 + libgo/go/math/big/arith_test.go | 335 ++++ libgo/go/math/big/calibrate_test.go | 88 + libgo/go/math/big/hilbert_test.go | 160 ++ libgo/go/math/big/int.go | 873 ++++++++++ libgo/go/math/big/int_test.go | 1403 ++++++++++++++++ libgo/go/math/big/nat.go | 1271 +++++++++++++++ libgo/go/math/big/nat_test.go | 669 ++++++++ libgo/go/math/big/rat.go | 432 +++++ libgo/go/math/big/rat_test.go | 456 ++++++ libgo/go/math/cmplx/abs.go | 12 + libgo/go/math/cmplx/asin.go | 170 ++ libgo/go/math/cmplx/cmath_test.go | 853 ++++++++++ libgo/go/math/cmplx/conj.go | 8 + libgo/go/math/cmplx/exp.go | 55 + libgo/go/math/cmplx/isinf.go | 21 + libgo/go/math/cmplx/isnan.go | 25 + libgo/go/math/cmplx/log.go | 64 + libgo/go/math/cmplx/phase.go | 11 + libgo/go/math/cmplx/polar.go | 12 + libgo/go/math/cmplx/pow.go | 60 + libgo/go/math/cmplx/rect.go | 13 + libgo/go/math/cmplx/sin.go | 132 ++ libgo/go/math/cmplx/sqrt.go | 103 ++ libgo/go/math/cmplx/tan.go | 184 +++ libgo/go/math/gamma.go | 6 +- libgo/go/math/rand/exp.go | 223 +++ libgo/go/math/rand/normal.go | 158 ++ libgo/go/math/rand/rand.go | 179 +++ libgo/go/math/rand/rand_test.go | 350 ++++ libgo/go/math/rand/rng.go | 246 +++ libgo/go/math/rand/zipf.go | 73 + libgo/go/math/tan.go | 140 +- libgo/go/mime/multipart/multipart.go | 2 +- libgo/go/mime/multipart/multipart_test.go | 6 +- libgo/go/net/dnsclient.go | 2 +- libgo/go/net/dnsclient_unix.go | 2 +- libgo/go/net/http/cgi/child.go | 192 +++ libgo/go/net/http/cgi/child_test.go | 87 + libgo/go/net/http/cgi/host.go | 350 ++++ libgo/go/net/http/cgi/host_test.go | 479 ++++++ libgo/go/net/http/cgi/matryoshka_test.go | 74 + libgo/go/net/http/cgi/testdata/test.cgi | 96 ++ libgo/go/net/http/chunked.go | 57 + libgo/go/net/http/client.go | 304 ++++ libgo/go/net/http/client_test.go | 318 ++++ libgo/go/net/http/cookie.go | 267 +++ libgo/go/net/http/cookie_test.go | 200 +++ libgo/go/net/http/doc.go | 79 + libgo/go/net/http/export_test.go | 41 + libgo/go/net/http/fcgi/child.go | 258 +++ libgo/go/net/http/fcgi/fcgi.go | 271 ++++ libgo/go/net/http/fcgi/fcgi_test.go | 113 ++ libgo/go/net/http/filetransport.go | 123 ++ libgo/go/net/http/filetransport_test.go | 62 + libgo/go/net/http/fs.go | 324 ++++ libgo/go/net/http/fs_test.go | 308 ++++ libgo/go/net/http/header.go | 78 + libgo/go/net/http/header_test.go | 81 + libgo/go/net/http/httptest/recorder.go | 58 + libgo/go/net/http/httptest/server.go | 177 ++ libgo/go/net/http/httputil/chunked.go | 84 + libgo/go/net/http/httputil/chunked_test.go | 35 + libgo/go/net/http/httputil/dump.go | 203 +++ libgo/go/net/http/httputil/dump_test.go | 140 ++ libgo/go/net/http/httputil/persist.go | 418 +++++ libgo/go/net/http/httputil/reverseproxy.go | 172 ++ libgo/go/net/http/httputil/reverseproxy_test.go | 71 + libgo/go/net/http/lex.go | 144 ++ libgo/go/net/http/lex_test.go | 70 + libgo/go/net/http/pprof/pprof.go | 133 ++ libgo/go/net/http/proxy_test.go | 48 + libgo/go/net/http/range_test.go | 57 + libgo/go/net/http/readrequest_test.go | 227 +++ libgo/go/net/http/request.go | 817 ++++++++++ libgo/go/net/http/request_test.go | 278 ++++ libgo/go/net/http/requestwrite_test.go | 444 +++++ libgo/go/net/http/response.go | 236 +++ libgo/go/net/http/response_test.go | 446 +++++ libgo/go/net/http/responsewrite_test.go | 109 ++ libgo/go/net/http/serve_test.go | 1155 +++++++++++++ libgo/go/net/http/server.go | 1189 ++++++++++++++ libgo/go/net/http/sniff.go | 214 +++ libgo/go/net/http/sniff_test.go | 81 + libgo/go/net/http/status.go | 106 ++ libgo/go/net/http/testdata/file | 1 + libgo/go/net/http/testdata/index.html | 1 + libgo/go/net/http/testdata/style.css | 1 + libgo/go/net/http/transfer.go | 628 ++++++++ libgo/go/net/http/transport.go | 740 +++++++++ libgo/go/net/http/transport_test.go | 639 ++++++++ libgo/go/net/http/transport_windows.go | 21 + libgo/go/net/http/triv.go | 149 ++ libgo/go/net/ip_test.go | 2 +- libgo/go/net/lookup_test.go | 4 - libgo/go/net/lookup_windows.go | 29 +- libgo/go/net/mail/message.go | 524 ++++++ libgo/go/net/mail/message_test.go | 277 ++++ libgo/go/net/net_test.go | 2 +- libgo/go/net/parse_test.go | 2 +- libgo/go/net/rpc/client.go | 287 ++++ libgo/go/net/rpc/debug.go | 90 ++ libgo/go/net/rpc/jsonrpc/all_test.go | 221 +++ libgo/go/net/rpc/jsonrpc/client.go | 123 ++ libgo/go/net/rpc/jsonrpc/server.go | 136 ++ libgo/go/net/rpc/server.go | 640 ++++++++ libgo/go/net/rpc/server_test.go | 597 +++++++ libgo/go/net/server_test.go | 2 +- libgo/go/net/smtp/auth.go | 67 + libgo/go/net/smtp/smtp.go | 293 ++++ libgo/go/net/smtp/smtp_test.go | 181 +++ libgo/go/net/sock_bsd.go | 2 +- libgo/go/net/textproto/reader.go | 2 +- libgo/go/net/url/url.go | 685 ++++++++ libgo/go/net/url/url_test.go | 749 +++++++++ libgo/go/old/netchan/common.go | 2 +- libgo/go/old/netchan/export.go | 2 +- libgo/go/old/regexp/regexp.go | 2 +- libgo/go/old/template/parse.go | 2 +- libgo/go/old/template/template_test.go | 2 +- libgo/go/os/dir_unix.go | 2 +- libgo/go/os/env_plan9.go | 2 +- libgo/go/os/env_windows.go | 2 +- libgo/go/os/error_plan9.go | 2 +- libgo/go/os/exec/exec.go | 393 +++++ libgo/go/os/exec/exec_test.go | 257 +++ libgo/go/os/exec/lp_plan9.go | 52 + libgo/go/os/exec/lp_test.go | 33 + libgo/go/os/exec/lp_unix.go | 55 + libgo/go/os/exec/lp_windows.go | 78 + libgo/go/os/exec_plan9.go | 3 +- libgo/go/os/file_unix.go | 6 +- libgo/go/os/path_test.go | 2 +- libgo/go/path/filepath/match.go | 2 +- libgo/go/path/filepath/match_test.go | 2 +- libgo/go/path/match.go | 2 +- libgo/go/rand/exp.go | 223 --- libgo/go/rand/normal.go | 158 -- libgo/go/rand/rand.go | 179 --- libgo/go/rand/rand_test.go | 350 ---- libgo/go/rand/rng.go | 246 --- libgo/go/rand/zipf.go | 73 - libgo/go/regexp/exec_test.go | 4 +- libgo/go/regexp/regexp.go | 2 +- libgo/go/regexp/syntax/parse.go | 2 +- libgo/go/regexp/testdata/re2-exhaustive.txt.bz2 | Bin 0 -> 394016 bytes libgo/go/rpc/client.go | 287 ---- libgo/go/rpc/debug.go | 90 -- libgo/go/rpc/jsonrpc/all_test.go | 221 --- libgo/go/rpc/jsonrpc/client.go | 123 -- libgo/go/rpc/jsonrpc/server.go | 136 -- libgo/go/rpc/server.go | 640 -------- libgo/go/rpc/server_test.go | 597 ------- libgo/go/runtime/export_test.go | 1 + libgo/go/runtime/softfloat64_test.go | 2 +- libgo/go/scanner/scanner.go | 670 -------- libgo/go/scanner/scanner_test.go | 563 ------- libgo/go/smtp/auth.go | 67 - libgo/go/smtp/smtp.go | 293 ---- libgo/go/smtp/smtp_test.go | 181 --- libgo/go/sort/sort_test.go | 2 +- libgo/go/strconv/quote.go | 2 +- libgo/go/strings/reader.go | 4 +- libgo/go/strings/strings.go | 2 +- libgo/go/strings/strings_test.go | 2 +- libgo/go/sync/once_test.go | 2 +- libgo/go/syslog/syslog.go | 149 -- libgo/go/syslog/syslog_c.c | 19 - libgo/go/syslog/syslog_libc.go | 36 - libgo/go/syslog/syslog_test.go | 113 -- libgo/go/syslog/syslog_unix.go | 31 - libgo/go/tabwriter/tabwriter.go | 561 ------- libgo/go/tabwriter/tabwriter_test.go | 614 ------- libgo/go/template/doc.go | 313 ---- libgo/go/template/exec.go | 673 -------- libgo/go/template/exec_test.go | 658 -------- libgo/go/template/funcs.go | 367 ----- libgo/go/template/helper.go | 241 --- libgo/go/template/parse.go | 96 -- libgo/go/template/parse/lex.go | 482 ------ libgo/go/template/parse/lex_test.go | 257 --- libgo/go/template/parse/node.go | 463 ------ libgo/go/template/parse/parse.go | 436 ----- libgo/go/template/parse/parse_test.go | 259 --- libgo/go/template/parse/set.go | 49 - libgo/go/template/set.go | 119 -- libgo/go/template/set_test.go | 239 --- libgo/go/template/testdata/file1.tmpl | 2 - libgo/go/template/testdata/file2.tmpl | 2 - libgo/go/template/testdata/tmpl1.tmpl | 1 - libgo/go/template/testdata/tmpl2.tmpl | 1 - libgo/go/testing/quick/quick.go | 2 +- libgo/go/testing/quick/quick_test.go | 2 +- libgo/go/testing/script/script.go | 2 +- libgo/go/text/scanner/scanner.go | 670 ++++++++ libgo/go/text/scanner/scanner_test.go | 563 +++++++ libgo/go/text/tabwriter/tabwriter.go | 561 +++++++ libgo/go/text/tabwriter/tabwriter_test.go | 614 +++++++ libgo/go/text/template/doc.go | 313 ++++ libgo/go/text/template/exec.go | 673 ++++++++ libgo/go/text/template/exec_test.go | 683 ++++++++ libgo/go/text/template/funcs.go | 367 +++++ libgo/go/text/template/helper.go | 241 +++ libgo/go/text/template/parse.go | 89 + libgo/go/text/template/parse/lex.go | 482 ++++++ libgo/go/text/template/parse/lex_test.go | 257 +++ libgo/go/text/template/parse/node.go | 463 ++++++ libgo/go/text/template/parse/parse.go | 436 +++++ libgo/go/text/template/parse/parse_test.go | 259 +++ libgo/go/text/template/parse/set.go | 49 + libgo/go/text/template/set.go | 120 ++ libgo/go/text/template/set_test.go | 239 +++ libgo/go/text/template/testdata/file1.tmpl | 2 + libgo/go/text/template/testdata/file2.tmpl | 2 + libgo/go/text/template/testdata/tmpl1.tmpl | 1 + libgo/go/text/template/testdata/tmpl2.tmpl | 1 + libgo/go/time/sleep_test.go | 4 +- libgo/go/time/sys.go | 18 +- libgo/go/time/zoneinfo_windows.go | 4 +- libgo/go/unicode/utf16/utf16.go | 101 ++ libgo/go/unicode/utf16/utf16_test.go | 91 ++ libgo/go/unicode/utf8/string.go | 199 +++ libgo/go/unicode/utf8/string_test.go | 114 ++ libgo/go/unicode/utf8/utf8.go | 391 +++++ libgo/go/unicode/utf8/utf8_test.go | 344 ++++ libgo/go/url/url.go | 685 -------- libgo/go/url/url_test.go | 749 --------- libgo/go/utf16/utf16.go | 101 -- libgo/go/utf16/utf16_test.go | 91 -- libgo/go/utf8/string.go | 199 --- libgo/go/utf8/string_test.go | 114 -- libgo/go/utf8/utf8.go | 391 ----- libgo/go/utf8/utf8_test.go | 344 ---- libgo/go/websocket/client.go | 2 +- libgo/go/websocket/hixie.go | 6 +- libgo/go/websocket/hixie_test.go | 4 +- libgo/go/websocket/hybi.go | 4 +- libgo/go/websocket/hybi_test.go | 4 +- libgo/go/websocket/server.go | 8 +- libgo/go/websocket/websocket.go | 6 +- libgo/go/websocket/websocket_test.go | 25 +- libgo/go/xml/atom_test.go | 50 - libgo/go/xml/embed_test.go | 124 -- libgo/go/xml/marshal.go | 304 ---- libgo/go/xml/marshal_test.go | 423 ----- libgo/go/xml/read.go | 630 -------- libgo/go/xml/read_test.go | 393 ----- libgo/go/xml/xml.go | 1697 -------------------- libgo/go/xml/xml_test.go | 609 ------- 569 files changed, 62746 insertions(+), 60394 deletions(-) delete mode 100644 libgo/go/asn1/asn1.go delete mode 100644 libgo/go/asn1/asn1_test.go delete mode 100644 libgo/go/asn1/common.go delete mode 100644 libgo/go/asn1/marshal.go delete mode 100644 libgo/go/asn1/marshal_test.go delete mode 100644 libgo/go/big/arith.go delete mode 100644 libgo/go/big/arith_decl.go delete mode 100644 libgo/go/big/arith_test.go delete mode 100644 libgo/go/big/calibrate_test.go delete mode 100644 libgo/go/big/hilbert_test.go delete mode 100644 libgo/go/big/int.go delete mode 100644 libgo/go/big/int_test.go delete mode 100644 libgo/go/big/nat.go delete mode 100644 libgo/go/big/nat_test.go delete mode 100644 libgo/go/big/rat.go delete mode 100644 libgo/go/big/rat_test.go delete mode 100644 libgo/go/cmath/abs.go delete mode 100644 libgo/go/cmath/asin.go delete mode 100644 libgo/go/cmath/cmath_test.go delete mode 100644 libgo/go/cmath/conj.go delete mode 100644 libgo/go/cmath/exp.go delete mode 100644 libgo/go/cmath/isinf.go delete mode 100644 libgo/go/cmath/isnan.go delete mode 100644 libgo/go/cmath/log.go delete mode 100644 libgo/go/cmath/phase.go delete mode 100644 libgo/go/cmath/polar.go delete mode 100644 libgo/go/cmath/pow.go delete mode 100644 libgo/go/cmath/rect.go delete mode 100644 libgo/go/cmath/sin.go delete mode 100644 libgo/go/cmath/sqrt.go delete mode 100644 libgo/go/cmath/tan.go delete mode 100644 libgo/go/compress/zlib/testdata/e.txt delete mode 100644 libgo/go/compress/zlib/testdata/pi.txt delete mode 100644 libgo/go/csv/reader.go delete mode 100644 libgo/go/csv/reader_test.go delete mode 100644 libgo/go/csv/writer.go delete mode 100644 libgo/go/csv/writer_test.go create mode 100644 libgo/go/encoding/asn1/asn1.go create mode 100644 libgo/go/encoding/asn1/asn1_test.go create mode 100644 libgo/go/encoding/asn1/common.go create mode 100644 libgo/go/encoding/asn1/marshal.go create mode 100644 libgo/go/encoding/asn1/marshal_test.go create mode 100644 libgo/go/encoding/csv/reader.go create mode 100644 libgo/go/encoding/csv/reader_test.go create mode 100644 libgo/go/encoding/csv/writer.go create mode 100644 libgo/go/encoding/csv/writer_test.go create mode 100644 libgo/go/encoding/gob/codec_test.go create mode 100644 libgo/go/encoding/gob/debug.go create mode 100644 libgo/go/encoding/gob/decode.go create mode 100644 libgo/go/encoding/gob/decoder.go create mode 100644 libgo/go/encoding/gob/doc.go create mode 100644 libgo/go/encoding/gob/dump.go create mode 100644 libgo/go/encoding/gob/encode.go create mode 100644 libgo/go/encoding/gob/encoder.go create mode 100644 libgo/go/encoding/gob/encoder_test.go create mode 100644 libgo/go/encoding/gob/error.go create mode 100644 libgo/go/encoding/gob/gobencdec_test.go create mode 100644 libgo/go/encoding/gob/timing_test.go create mode 100644 libgo/go/encoding/gob/type.go create mode 100644 libgo/go/encoding/gob/type_test.go create mode 100644 libgo/go/encoding/json/decode.go create mode 100644 libgo/go/encoding/json/decode_test.go create mode 100644 libgo/go/encoding/json/encode.go create mode 100644 libgo/go/encoding/json/encode_test.go create mode 100644 libgo/go/encoding/json/indent.go create mode 100644 libgo/go/encoding/json/scanner.go create mode 100644 libgo/go/encoding/json/scanner_test.go create mode 100644 libgo/go/encoding/json/stream.go create mode 100644 libgo/go/encoding/json/stream_test.go create mode 100644 libgo/go/encoding/json/tagkey_test.go create mode 100644 libgo/go/encoding/json/tags.go create mode 100644 libgo/go/encoding/json/tags_test.go create mode 100644 libgo/go/encoding/xml/atom_test.go create mode 100644 libgo/go/encoding/xml/embed_test.go create mode 100644 libgo/go/encoding/xml/marshal.go create mode 100644 libgo/go/encoding/xml/marshal_test.go create mode 100644 libgo/go/encoding/xml/read.go create mode 100644 libgo/go/encoding/xml/read_test.go create mode 100644 libgo/go/encoding/xml/xml.go create mode 100644 libgo/go/encoding/xml/xml_test.go delete mode 100644 libgo/go/exec/exec.go delete mode 100644 libgo/go/exec/exec_test.go delete mode 100644 libgo/go/exec/lp_plan9.go delete mode 100644 libgo/go/exec/lp_test.go delete mode 100644 libgo/go/exec/lp_unix.go delete mode 100644 libgo/go/exec/lp_windows.go create mode 100644 libgo/go/exp/sql/driver/types_test.go create mode 100644 libgo/go/exp/ssh/client_auth.go delete mode 100644 libgo/go/exp/template/html/attr.go delete mode 100644 libgo/go/exp/template/html/clone.go delete mode 100644 libgo/go/exp/template/html/clone_test.go delete mode 100644 libgo/go/exp/template/html/content.go delete mode 100644 libgo/go/exp/template/html/content_test.go delete mode 100644 libgo/go/exp/template/html/context.go delete mode 100644 libgo/go/exp/template/html/css.go delete mode 100644 libgo/go/exp/template/html/css_test.go delete mode 100644 libgo/go/exp/template/html/doc.go delete mode 100644 libgo/go/exp/template/html/error.go delete mode 100644 libgo/go/exp/template/html/escape.go delete mode 100644 libgo/go/exp/template/html/escape_test.go delete mode 100644 libgo/go/exp/template/html/html.go delete mode 100644 libgo/go/exp/template/html/html_test.go delete mode 100644 libgo/go/exp/template/html/js.go delete mode 100644 libgo/go/exp/template/html/js_test.go delete mode 100644 libgo/go/exp/template/html/transition.go delete mode 100644 libgo/go/exp/template/html/url.go delete mode 100644 libgo/go/exp/template/html/url_test.go create mode 100644 libgo/go/go/ast/import.go delete mode 100644 libgo/go/gob/codec_test.go delete mode 100644 libgo/go/gob/decode.go delete mode 100644 libgo/go/gob/decoder.go delete mode 100644 libgo/go/gob/doc.go delete mode 100644 libgo/go/gob/encode.go delete mode 100644 libgo/go/gob/encoder.go delete mode 100644 libgo/go/gob/encoder_test.go delete mode 100644 libgo/go/gob/error.go delete mode 100644 libgo/go/gob/gobencdec_test.go delete mode 100644 libgo/go/gob/timing_test.go delete mode 100644 libgo/go/gob/type.go delete mode 100644 libgo/go/gob/type_test.go create mode 100644 libgo/go/html/template/attr.go create mode 100644 libgo/go/html/template/clone.go create mode 100644 libgo/go/html/template/clone_test.go create mode 100644 libgo/go/html/template/content.go create mode 100644 libgo/go/html/template/content_test.go create mode 100644 libgo/go/html/template/context.go create mode 100644 libgo/go/html/template/css.go create mode 100644 libgo/go/html/template/css_test.go create mode 100644 libgo/go/html/template/doc.go create mode 100644 libgo/go/html/template/error.go create mode 100644 libgo/go/html/template/escape.go create mode 100644 libgo/go/html/template/escape_test.go create mode 100644 libgo/go/html/template/html.go create mode 100644 libgo/go/html/template/html_test.go create mode 100644 libgo/go/html/template/js.go create mode 100644 libgo/go/html/template/js_test.go create mode 100644 libgo/go/html/template/template.go create mode 100644 libgo/go/html/template/transition.go create mode 100644 libgo/go/html/template/url.go create mode 100644 libgo/go/html/template/url_test.go create mode 100644 libgo/go/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat delete mode 100644 libgo/go/http/cgi/child.go delete mode 100644 libgo/go/http/cgi/child_test.go delete mode 100644 libgo/go/http/cgi/host.go delete mode 100644 libgo/go/http/cgi/host_test.go delete mode 100644 libgo/go/http/cgi/matryoshka_test.go delete mode 100755 libgo/go/http/cgi/testdata/test.cgi delete mode 100644 libgo/go/http/chunked.go delete mode 100644 libgo/go/http/client.go delete mode 100644 libgo/go/http/client_test.go delete mode 100644 libgo/go/http/cookie.go delete mode 100644 libgo/go/http/cookie_test.go delete mode 100644 libgo/go/http/doc.go delete mode 100644 libgo/go/http/dump.go delete mode 100644 libgo/go/http/export_test.go delete mode 100644 libgo/go/http/fcgi/child.go delete mode 100644 libgo/go/http/fcgi/fcgi.go delete mode 100644 libgo/go/http/fcgi/fcgi_test.go delete mode 100644 libgo/go/http/filetransport.go delete mode 100644 libgo/go/http/filetransport_test.go delete mode 100644 libgo/go/http/fs.go delete mode 100644 libgo/go/http/fs_test.go delete mode 100644 libgo/go/http/header.go delete mode 100644 libgo/go/http/header_test.go delete mode 100644 libgo/go/http/httptest/recorder.go delete mode 100644 libgo/go/http/httptest/server.go delete mode 100644 libgo/go/http/lex.go delete mode 100644 libgo/go/http/lex_test.go delete mode 100644 libgo/go/http/persist.go delete mode 100644 libgo/go/http/pprof/pprof.go delete mode 100644 libgo/go/http/proxy_test.go delete mode 100644 libgo/go/http/range_test.go delete mode 100644 libgo/go/http/readrequest_test.go delete mode 100644 libgo/go/http/request.go delete mode 100644 libgo/go/http/request_test.go delete mode 100644 libgo/go/http/requestwrite_test.go delete mode 100644 libgo/go/http/response.go delete mode 100644 libgo/go/http/response_test.go delete mode 100644 libgo/go/http/responsewrite_test.go delete mode 100644 libgo/go/http/reverseproxy.go delete mode 100644 libgo/go/http/reverseproxy_test.go delete mode 100644 libgo/go/http/serve_test.go delete mode 100644 libgo/go/http/server.go delete mode 100644 libgo/go/http/sniff.go delete mode 100644 libgo/go/http/sniff_test.go delete mode 100644 libgo/go/http/status.go delete mode 100644 libgo/go/http/testdata/file delete mode 100644 libgo/go/http/testdata/index.html delete mode 100644 libgo/go/http/testdata/style.css delete mode 100644 libgo/go/http/transfer.go delete mode 100644 libgo/go/http/transport.go delete mode 100644 libgo/go/http/transport_test.go delete mode 100644 libgo/go/http/transport_windows.go delete mode 100644 libgo/go/json/decode.go delete mode 100644 libgo/go/json/decode_test.go delete mode 100644 libgo/go/json/encode.go delete mode 100644 libgo/go/json/encode_test.go delete mode 100644 libgo/go/json/indent.go delete mode 100644 libgo/go/json/scanner.go delete mode 100644 libgo/go/json/scanner_test.go delete mode 100644 libgo/go/json/stream.go delete mode 100644 libgo/go/json/stream_test.go delete mode 100644 libgo/go/json/tagkey_test.go delete mode 100644 libgo/go/json/tags.go delete mode 100644 libgo/go/json/tags_test.go create mode 100644 libgo/go/log/syslog/syslog.go create mode 100644 libgo/go/log/syslog/syslog_c.c create mode 100644 libgo/go/log/syslog/syslog_libc.go create mode 100644 libgo/go/log/syslog/syslog_test.go create mode 100644 libgo/go/log/syslog/syslog_unix.go delete mode 100644 libgo/go/mail/message.go delete mode 100644 libgo/go/mail/message_test.go create mode 100644 libgo/go/math/big/arith.go create mode 100644 libgo/go/math/big/arith_decl.go create mode 100644 libgo/go/math/big/arith_test.go create mode 100644 libgo/go/math/big/calibrate_test.go create mode 100644 libgo/go/math/big/hilbert_test.go create mode 100644 libgo/go/math/big/int.go create mode 100644 libgo/go/math/big/int_test.go create mode 100644 libgo/go/math/big/nat.go create mode 100644 libgo/go/math/big/nat_test.go create mode 100644 libgo/go/math/big/rat.go create mode 100644 libgo/go/math/big/rat_test.go create mode 100644 libgo/go/math/cmplx/abs.go create mode 100644 libgo/go/math/cmplx/asin.go create mode 100644 libgo/go/math/cmplx/cmath_test.go create mode 100644 libgo/go/math/cmplx/conj.go create mode 100644 libgo/go/math/cmplx/exp.go create mode 100644 libgo/go/math/cmplx/isinf.go create mode 100644 libgo/go/math/cmplx/isnan.go create mode 100644 libgo/go/math/cmplx/log.go create mode 100644 libgo/go/math/cmplx/phase.go create mode 100644 libgo/go/math/cmplx/polar.go create mode 100644 libgo/go/math/cmplx/pow.go create mode 100644 libgo/go/math/cmplx/rect.go create mode 100644 libgo/go/math/cmplx/sin.go create mode 100644 libgo/go/math/cmplx/sqrt.go create mode 100644 libgo/go/math/cmplx/tan.go create mode 100644 libgo/go/math/rand/exp.go create mode 100644 libgo/go/math/rand/normal.go create mode 100644 libgo/go/math/rand/rand.go create mode 100644 libgo/go/math/rand/rand_test.go create mode 100644 libgo/go/math/rand/rng.go create mode 100644 libgo/go/math/rand/zipf.go create mode 100644 libgo/go/net/http/cgi/child.go create mode 100644 libgo/go/net/http/cgi/child_test.go create mode 100644 libgo/go/net/http/cgi/host.go create mode 100644 libgo/go/net/http/cgi/host_test.go create mode 100644 libgo/go/net/http/cgi/matryoshka_test.go create mode 100644 libgo/go/net/http/cgi/testdata/test.cgi create mode 100644 libgo/go/net/http/chunked.go create mode 100644 libgo/go/net/http/client.go create mode 100644 libgo/go/net/http/client_test.go create mode 100644 libgo/go/net/http/cookie.go create mode 100644 libgo/go/net/http/cookie_test.go create mode 100644 libgo/go/net/http/doc.go create mode 100644 libgo/go/net/http/export_test.go create mode 100644 libgo/go/net/http/fcgi/child.go create mode 100644 libgo/go/net/http/fcgi/fcgi.go create mode 100644 libgo/go/net/http/fcgi/fcgi_test.go create mode 100644 libgo/go/net/http/filetransport.go create mode 100644 libgo/go/net/http/filetransport_test.go create mode 100644 libgo/go/net/http/fs.go create mode 100644 libgo/go/net/http/fs_test.go create mode 100644 libgo/go/net/http/header.go create mode 100644 libgo/go/net/http/header_test.go create mode 100644 libgo/go/net/http/httptest/recorder.go create mode 100644 libgo/go/net/http/httptest/server.go create mode 100644 libgo/go/net/http/httputil/chunked.go create mode 100644 libgo/go/net/http/httputil/chunked_test.go create mode 100644 libgo/go/net/http/httputil/dump.go create mode 100644 libgo/go/net/http/httputil/dump_test.go create mode 100644 libgo/go/net/http/httputil/persist.go create mode 100644 libgo/go/net/http/httputil/reverseproxy.go create mode 100644 libgo/go/net/http/httputil/reverseproxy_test.go create mode 100644 libgo/go/net/http/lex.go create mode 100644 libgo/go/net/http/lex_test.go create mode 100644 libgo/go/net/http/pprof/pprof.go create mode 100644 libgo/go/net/http/proxy_test.go create mode 100644 libgo/go/net/http/range_test.go create mode 100644 libgo/go/net/http/readrequest_test.go create mode 100644 libgo/go/net/http/request.go create mode 100644 libgo/go/net/http/request_test.go create mode 100644 libgo/go/net/http/requestwrite_test.go create mode 100644 libgo/go/net/http/response.go create mode 100644 libgo/go/net/http/response_test.go create mode 100644 libgo/go/net/http/responsewrite_test.go create mode 100644 libgo/go/net/http/serve_test.go create mode 100644 libgo/go/net/http/server.go create mode 100644 libgo/go/net/http/sniff.go create mode 100644 libgo/go/net/http/sniff_test.go create mode 100644 libgo/go/net/http/status.go create mode 100644 libgo/go/net/http/testdata/file create mode 100644 libgo/go/net/http/testdata/index.html create mode 100644 libgo/go/net/http/testdata/style.css create mode 100644 libgo/go/net/http/transfer.go create mode 100644 libgo/go/net/http/transport.go create mode 100644 libgo/go/net/http/transport_test.go create mode 100644 libgo/go/net/http/transport_windows.go create mode 100644 libgo/go/net/http/triv.go create mode 100644 libgo/go/net/mail/message.go create mode 100644 libgo/go/net/mail/message_test.go create mode 100644 libgo/go/net/rpc/client.go create mode 100644 libgo/go/net/rpc/debug.go create mode 100644 libgo/go/net/rpc/jsonrpc/all_test.go create mode 100644 libgo/go/net/rpc/jsonrpc/client.go create mode 100644 libgo/go/net/rpc/jsonrpc/server.go create mode 100644 libgo/go/net/rpc/server.go create mode 100644 libgo/go/net/rpc/server_test.go create mode 100644 libgo/go/net/smtp/auth.go create mode 100644 libgo/go/net/smtp/smtp.go create mode 100644 libgo/go/net/smtp/smtp_test.go create mode 100644 libgo/go/net/url/url.go create mode 100644 libgo/go/net/url/url_test.go create mode 100644 libgo/go/os/exec/exec.go create mode 100644 libgo/go/os/exec/exec_test.go create mode 100644 libgo/go/os/exec/lp_plan9.go create mode 100644 libgo/go/os/exec/lp_test.go create mode 100644 libgo/go/os/exec/lp_unix.go create mode 100644 libgo/go/os/exec/lp_windows.go delete mode 100644 libgo/go/rand/exp.go delete mode 100644 libgo/go/rand/normal.go delete mode 100644 libgo/go/rand/rand.go delete mode 100644 libgo/go/rand/rand_test.go delete mode 100644 libgo/go/rand/rng.go delete mode 100644 libgo/go/rand/zipf.go create mode 100644 libgo/go/regexp/testdata/re2-exhaustive.txt.bz2 delete mode 100644 libgo/go/rpc/client.go delete mode 100644 libgo/go/rpc/debug.go delete mode 100644 libgo/go/rpc/jsonrpc/all_test.go delete mode 100644 libgo/go/rpc/jsonrpc/client.go delete mode 100644 libgo/go/rpc/jsonrpc/server.go delete mode 100644 libgo/go/rpc/server.go delete mode 100644 libgo/go/rpc/server_test.go delete mode 100644 libgo/go/scanner/scanner.go delete mode 100644 libgo/go/scanner/scanner_test.go delete mode 100644 libgo/go/smtp/auth.go delete mode 100644 libgo/go/smtp/smtp.go delete mode 100644 libgo/go/smtp/smtp_test.go delete mode 100644 libgo/go/syslog/syslog.go delete mode 100644 libgo/go/syslog/syslog_c.c delete mode 100644 libgo/go/syslog/syslog_libc.go delete mode 100644 libgo/go/syslog/syslog_test.go delete mode 100644 libgo/go/syslog/syslog_unix.go delete mode 100644 libgo/go/tabwriter/tabwriter.go delete mode 100644 libgo/go/tabwriter/tabwriter_test.go delete mode 100644 libgo/go/template/doc.go delete mode 100644 libgo/go/template/exec.go delete mode 100644 libgo/go/template/exec_test.go delete mode 100644 libgo/go/template/funcs.go delete mode 100644 libgo/go/template/helper.go delete mode 100644 libgo/go/template/parse.go delete mode 100644 libgo/go/template/parse/lex.go delete mode 100644 libgo/go/template/parse/lex_test.go delete mode 100644 libgo/go/template/parse/node.go delete mode 100644 libgo/go/template/parse/parse.go delete mode 100644 libgo/go/template/parse/parse_test.go delete mode 100644 libgo/go/template/parse/set.go delete mode 100644 libgo/go/template/set.go delete mode 100644 libgo/go/template/set_test.go delete mode 100644 libgo/go/template/testdata/file1.tmpl delete mode 100644 libgo/go/template/testdata/file2.tmpl delete mode 100644 libgo/go/template/testdata/tmpl1.tmpl delete mode 100644 libgo/go/template/testdata/tmpl2.tmpl create mode 100644 libgo/go/text/scanner/scanner.go create mode 100644 libgo/go/text/scanner/scanner_test.go create mode 100644 libgo/go/text/tabwriter/tabwriter.go create mode 100644 libgo/go/text/tabwriter/tabwriter_test.go create mode 100644 libgo/go/text/template/doc.go create mode 100644 libgo/go/text/template/exec.go create mode 100644 libgo/go/text/template/exec_test.go create mode 100644 libgo/go/text/template/funcs.go create mode 100644 libgo/go/text/template/helper.go create mode 100644 libgo/go/text/template/parse.go create mode 100644 libgo/go/text/template/parse/lex.go create mode 100644 libgo/go/text/template/parse/lex_test.go create mode 100644 libgo/go/text/template/parse/node.go create mode 100644 libgo/go/text/template/parse/parse.go create mode 100644 libgo/go/text/template/parse/parse_test.go create mode 100644 libgo/go/text/template/parse/set.go create mode 100644 libgo/go/text/template/set.go create mode 100644 libgo/go/text/template/set_test.go create mode 100644 libgo/go/text/template/testdata/file1.tmpl create mode 100644 libgo/go/text/template/testdata/file2.tmpl create mode 100644 libgo/go/text/template/testdata/tmpl1.tmpl create mode 100644 libgo/go/text/template/testdata/tmpl2.tmpl create mode 100644 libgo/go/unicode/utf16/utf16.go create mode 100644 libgo/go/unicode/utf16/utf16_test.go create mode 100644 libgo/go/unicode/utf8/string.go create mode 100644 libgo/go/unicode/utf8/string_test.go create mode 100644 libgo/go/unicode/utf8/utf8.go create mode 100644 libgo/go/unicode/utf8/utf8_test.go delete mode 100644 libgo/go/url/url.go delete mode 100644 libgo/go/url/url_test.go delete mode 100644 libgo/go/utf16/utf16.go delete mode 100644 libgo/go/utf16/utf16_test.go delete mode 100644 libgo/go/utf8/string.go delete mode 100644 libgo/go/utf8/string_test.go delete mode 100644 libgo/go/utf8/utf8.go delete mode 100644 libgo/go/utf8/utf8_test.go delete mode 100644 libgo/go/xml/atom_test.go delete mode 100644 libgo/go/xml/embed_test.go delete mode 100644 libgo/go/xml/marshal.go delete mode 100644 libgo/go/xml/marshal_test.go delete mode 100644 libgo/go/xml/read.go delete mode 100644 libgo/go/xml/read_test.go delete mode 100644 libgo/go/xml/xml.go delete mode 100644 libgo/go/xml/xml_test.go (limited to 'libgo/go') diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go index 65bf120..facba2c 100644 --- a/libgo/go/archive/tar/reader.go +++ b/libgo/go/archive/tar/reader.go @@ -29,7 +29,7 @@ var ( // tr := tar.NewReader(r) // for { // hdr, err := tr.Next() -// if err == os.EOF { +// if err == io.EOF { // // end of tar archive // break // } @@ -200,7 +200,7 @@ func (tr *Reader) readHeader() *Header { } // Read reads from the current entry in the tar archive. -// It returns 0, os.EOF when it reaches the end of that entry, +// It returns 0, io.EOF when it reaches the end of that entry, // until Next is called to advance to the next entry. func (tr *Reader) Read(b []byte) (n int, err error) { if tr.nb == 0 { diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go index 64152b4..cfbe549 100644 --- a/libgo/go/archive/zip/reader.go +++ b/libgo/go/archive/zip/reader.go @@ -7,10 +7,10 @@ package zip import ( "bufio" "compress/flate" + "encoding/binary" "errors" "hash" "hash/crc32" - "encoding/binary" "io" "io/ioutil" "os" @@ -60,6 +60,7 @@ func OpenReader(name string) (*ReadCloser, error) { f.Close() return nil, err } + r.f = f return r, nil } diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go index 4d80aab..ca0b04e 100644 --- a/libgo/go/archive/zip/reader_test.go +++ b/libgo/go/archive/zip/reader_test.go @@ -98,7 +98,11 @@ func readTestZip(t *testing.T, zt ZipTest) { if err == FormatError { return } - defer z.Close() + defer func() { + if err := z.Close(); err != nil { + t.Errorf("error %q when closing zip file", err) + } + }() // bail here if no Files expected to be tested // (there may actually be files in the zip, but we don't care) diff --git a/libgo/go/archive/zip/writer_test.go b/libgo/go/archive/zip/writer_test.go index b562f84..25491dc 100644 --- a/libgo/go/archive/zip/writer_test.go +++ b/libgo/go/archive/zip/writer_test.go @@ -7,7 +7,7 @@ package zip import ( "bytes" "io/ioutil" - "rand" + "math/rand" "testing" ) diff --git a/libgo/go/asn1/asn1.go b/libgo/go/asn1/asn1.go deleted file mode 100644 index 73e733e..0000000 --- a/libgo/go/asn1/asn1.go +++ /dev/null @@ -1,841 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package asn1 implements parsing of DER-encoded ASN.1 data structures, -// as defined in ITU-T Rec X.690. -// -// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,'' -// http://luca.ntop.org/Teaching/Appunti/asn1.html. -package asn1 - -// ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc -// are different encoding formats for those objects. Here, we'll be dealing -// with DER, the Distinguished Encoding Rules. DER is used in X.509 because -// it's fast to parse and, unlike BER, has a unique encoding for every object. -// When calculating hashes over objects, it's important that the resulting -// bytes be the same at both ends and DER removes this margin of error. -// -// ASN.1 is very complex and this package doesn't attempt to implement -// everything by any means. - -import ( - "big" - "fmt" - "reflect" - "time" -) - -// A StructuralError suggests that the ASN.1 data is valid, but the Go type -// which is receiving it doesn't match. -type StructuralError struct { - Msg string -} - -func (e StructuralError) Error() string { return "ASN.1 structure error: " + e.Msg } - -// A SyntaxError suggests that the ASN.1 data is invalid. -type SyntaxError struct { - Msg string -} - -func (e SyntaxError) Error() string { return "ASN.1 syntax error: " + e.Msg } - -// We start by dealing with each of the primitive types in turn. - -// BOOLEAN - -func parseBool(bytes []byte) (ret bool, err error) { - if len(bytes) != 1 { - err = SyntaxError{"invalid boolean"} - return - } - - return bytes[0] != 0, nil -} - -// INTEGER - -// parseInt64 treats the given bytes as a big-endian, signed integer and -// returns the result. -func parseInt64(bytes []byte) (ret int64, err error) { - if len(bytes) > 8 { - // We'll overflow an int64 in this case. - err = StructuralError{"integer too large"} - return - } - for bytesRead := 0; bytesRead < len(bytes); bytesRead++ { - ret <<= 8 - ret |= int64(bytes[bytesRead]) - } - - // Shift up and down in order to sign extend the result. - ret <<= 64 - uint8(len(bytes))*8 - ret >>= 64 - uint8(len(bytes))*8 - return -} - -// parseInt treats the given bytes as a big-endian, signed integer and returns -// the result. -func parseInt(bytes []byte) (int, error) { - ret64, err := parseInt64(bytes) - if err != nil { - return 0, err - } - if ret64 != int64(int(ret64)) { - return 0, StructuralError{"integer too large"} - } - return int(ret64), nil -} - -var bigOne = big.NewInt(1) - -// parseBigInt treats the given bytes as a big-endian, signed integer and returns -// the result. -func parseBigInt(bytes []byte) *big.Int { - ret := new(big.Int) - if len(bytes) > 0 && bytes[0]&0x80 == 0x80 { - // This is a negative number. - notBytes := make([]byte, len(bytes)) - for i := range notBytes { - notBytes[i] = ^bytes[i] - } - ret.SetBytes(notBytes) - ret.Add(ret, bigOne) - ret.Neg(ret) - return ret - } - ret.SetBytes(bytes) - return ret -} - -// BIT STRING - -// BitString is the structure to use when you want an ASN.1 BIT STRING type. A -// bit string is padded up to the nearest byte in memory and the number of -// valid bits is recorded. Padding bits will be zero. -type BitString struct { - Bytes []byte // bits packed into bytes. - BitLength int // length in bits. -} - -// At returns the bit at the given index. If the index is out of range it -// returns false. -func (b BitString) At(i int) int { - if i < 0 || i >= b.BitLength { - return 0 - } - x := i / 8 - y := 7 - uint(i%8) - return int(b.Bytes[x]>>y) & 1 -} - -// RightAlign returns a slice where the padding bits are at the beginning. The -// slice may share memory with the BitString. -func (b BitString) RightAlign() []byte { - shift := uint(8 - (b.BitLength % 8)) - if shift == 8 || len(b.Bytes) == 0 { - return b.Bytes - } - - a := make([]byte, len(b.Bytes)) - a[0] = b.Bytes[0] >> shift - for i := 1; i < len(b.Bytes); i++ { - a[i] = b.Bytes[i-1] << (8 - shift) - a[i] |= b.Bytes[i] >> shift - } - - return a -} - -// parseBitString parses an ASN.1 bit string from the given byte slice and returns it. -func parseBitString(bytes []byte) (ret BitString, err error) { - if len(bytes) == 0 { - err = SyntaxError{"zero length BIT STRING"} - return - } - paddingBits := int(bytes[0]) - if paddingBits > 7 || - len(bytes) == 1 && paddingBits > 0 || - bytes[len(bytes)-1]&((1< 4 { - err = StructuralError{"base 128 integer too large"} - return - } - ret <<= 7 - b := bytes[offset] - ret |= int(b & 0x7f) - offset++ - if b&0x80 == 0 { - return - } - } - err = SyntaxError{"truncated base 128 integer"} - return -} - -// UTCTime - -func parseUTCTime(bytes []byte) (ret *time.Time, err error) { - s := string(bytes) - ret, err = time.Parse("0601021504Z0700", s) - if err == nil { - return - } - ret, err = time.Parse("060102150405Z0700", s) - return -} - -// parseGeneralizedTime parses the GeneralizedTime from the given byte slice -// and returns the resulting time. -func parseGeneralizedTime(bytes []byte) (ret *time.Time, err error) { - return time.Parse("20060102150405Z0700", string(bytes)) -} - -// PrintableString - -// parsePrintableString parses a ASN.1 PrintableString from the given byte -// array and returns it. -func parsePrintableString(bytes []byte) (ret string, err error) { - for _, b := range bytes { - if !isPrintable(b) { - err = SyntaxError{"PrintableString contains invalid character"} - return - } - } - ret = string(bytes) - return -} - -// isPrintable returns true iff the given b is in the ASN.1 PrintableString set. -func isPrintable(b byte) bool { - return 'a' <= b && b <= 'z' || - 'A' <= b && b <= 'Z' || - '0' <= b && b <= '9' || - '\'' <= b && b <= ')' || - '+' <= b && b <= '/' || - b == ' ' || - b == ':' || - b == '=' || - b == '?' || - // This is technically not allowed in a PrintableString. - // However, x509 certificates with wildcard strings don't - // always use the correct string type so we permit it. - b == '*' -} - -// IA5String - -// parseIA5String parses a ASN.1 IA5String (ASCII string) from the given -// byte slice and returns it. -func parseIA5String(bytes []byte) (ret string, err error) { - for _, b := range bytes { - if b >= 0x80 { - err = SyntaxError{"IA5String contains invalid character"} - return - } - } - ret = string(bytes) - return -} - -// T61String - -// parseT61String parses a ASN.1 T61String (8-bit clean string) from the given -// byte slice and returns it. -func parseT61String(bytes []byte) (ret string, err error) { - return string(bytes), nil -} - -// UTF8String - -// parseUTF8String parses a ASN.1 UTF8String (raw UTF-8) from the given byte -// array and returns it. -func parseUTF8String(bytes []byte) (ret string, err error) { - return string(bytes), nil -} - -// A RawValue represents an undecoded ASN.1 object. -type RawValue struct { - Class, Tag int - IsCompound bool - Bytes []byte - FullBytes []byte // includes the tag and length -} - -// RawContent is used to signal that the undecoded, DER data needs to be -// preserved for a struct. To use it, the first field of the struct must have -// this type. It's an error for any of the other fields to have this type. -type RawContent []byte - -// Tagging - -// parseTagAndLength parses an ASN.1 tag and length pair from the given offset -// into a byte slice. It returns the parsed data and the new offset. SET and -// SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we -// don't distinguish between ordered and unordered objects in this code. -func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) { - offset = initOffset - b := bytes[offset] - offset++ - ret.class = int(b >> 6) - ret.isCompound = b&0x20 == 0x20 - ret.tag = int(b & 0x1f) - - // If the bottom five bits are set, then the tag number is actually base 128 - // encoded afterwards - if ret.tag == 0x1f { - ret.tag, offset, err = parseBase128Int(bytes, offset) - if err != nil { - return - } - } - if offset >= len(bytes) { - err = SyntaxError{"truncated tag or length"} - return - } - b = bytes[offset] - offset++ - if b&0x80 == 0 { - // The length is encoded in the bottom 7 bits. - ret.length = int(b & 0x7f) - } else { - // Bottom 7 bits give the number of length bytes to follow. - numBytes := int(b & 0x7f) - // We risk overflowing a signed 32-bit number if we accept more than 3 bytes. - if numBytes > 3 { - err = StructuralError{"length too large"} - return - } - if numBytes == 0 { - err = SyntaxError{"indefinite length found (not DER)"} - return - } - ret.length = 0 - for i := 0; i < numBytes; i++ { - if offset >= len(bytes) { - err = SyntaxError{"truncated tag or length"} - return - } - b = bytes[offset] - offset++ - ret.length <<= 8 - ret.length |= int(b) - } - } - - return -} - -// parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse -// a number of ASN.1 values from the given byte slice and returns them as a -// slice of Go values of the given type. -func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err error) { - expectedTag, compoundType, ok := getUniversalType(elemType) - if !ok { - err = StructuralError{"unknown Go type for slice"} - return - } - - // First we iterate over the input and count the number of elements, - // checking that the types are correct in each case. - numElements := 0 - for offset := 0; offset < len(bytes); { - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - // We pretend that GENERAL STRINGs are PRINTABLE STRINGs so - // that a sequence of them can be parsed into a []string. - if t.tag == tagGeneralString { - t.tag = tagPrintableString - } - if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag { - err = StructuralError{"sequence tag mismatch"} - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"truncated sequence"} - return - } - offset += t.length - numElements++ - } - ret = reflect.MakeSlice(sliceType, numElements, numElements) - params := fieldParameters{} - offset := 0 - for i := 0; i < numElements; i++ { - offset, err = parseField(ret.Index(i), bytes, offset, params) - if err != nil { - return - } - } - return -} - -var ( - bitStringType = reflect.TypeOf(BitString{}) - objectIdentifierType = reflect.TypeOf(ObjectIdentifier{}) - enumeratedType = reflect.TypeOf(Enumerated(0)) - flagType = reflect.TypeOf(Flag(false)) - timeType = reflect.TypeOf(&time.Time{}) - rawValueType = reflect.TypeOf(RawValue{}) - rawContentsType = reflect.TypeOf(RawContent(nil)) - bigIntType = reflect.TypeOf(new(big.Int)) -) - -// invalidLength returns true iff offset + length > sliceLength, or if the -// addition would overflow. -func invalidLength(offset, length, sliceLength int) bool { - return offset+length < offset || offset+length > sliceLength -} - -// parseField is the main parsing function. Given a byte slice and an offset -// into the array, it will try to parse a suitable ASN.1 value out and store it -// in the given Value. -func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err error) { - offset = initOffset - fieldType := v.Type() - - // If we have run out of data, it may be that there are optional elements at the end. - if offset == len(bytes) { - if !setDefaultValue(v, params) { - err = SyntaxError{"sequence truncated"} - } - return - } - - // Deal with raw values. - if fieldType == rawValueType { - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]} - offset += t.length - v.Set(reflect.ValueOf(result)) - return - } - - // Deal with the ANY type. - if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 { - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - var result interface{} - if !t.isCompound && t.class == classUniversal { - innerBytes := bytes[offset : offset+t.length] - switch t.tag { - case tagPrintableString: - result, err = parsePrintableString(innerBytes) - case tagIA5String: - result, err = parseIA5String(innerBytes) - case tagT61String: - result, err = parseT61String(innerBytes) - case tagUTF8String: - result, err = parseUTF8String(innerBytes) - case tagInteger: - result, err = parseInt64(innerBytes) - case tagBitString: - result, err = parseBitString(innerBytes) - case tagOID: - result, err = parseObjectIdentifier(innerBytes) - case tagUTCTime: - result, err = parseUTCTime(innerBytes) - case tagOctetString: - result = innerBytes - default: - // If we don't know how to handle the type, we just leave Value as nil. - } - } - offset += t.length - if err != nil { - return - } - if result != nil { - v.Set(reflect.ValueOf(result)) - } - return - } - universalTag, compoundType, ok1 := getUniversalType(fieldType) - if !ok1 { - err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)} - return - } - - t, offset, err := parseTagAndLength(bytes, offset) - if err != nil { - return - } - if params.explicit { - expectedClass := classContextSpecific - if params.application { - expectedClass = classApplication - } - if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) { - if t.length > 0 { - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - } else { - if fieldType != flagType { - err = StructuralError{"Zero length explicit tag was not an asn1.Flag"} - return - } - v.SetBool(true) - return - } - } else { - // The tags didn't match, it might be an optional element. - ok := setDefaultValue(v, params) - if ok { - offset = initOffset - } else { - err = StructuralError{"explicitly tagged member didn't match"} - } - return - } - } - - // Special case for strings: all the ASN.1 string types map to the Go - // type string. getUniversalType returns the tag for PrintableString - // when it sees a string, so if we see a different string type on the - // wire, we change the universal type to match. - if universalTag == tagPrintableString { - switch t.tag { - case tagIA5String, tagGeneralString, tagT61String, tagUTF8String: - universalTag = t.tag - } - } - - // Special case for time: UTCTime and GeneralizedTime both map to the - // Go type time.Time. - if universalTag == tagUTCTime && t.tag == tagGeneralizedTime { - universalTag = tagGeneralizedTime - } - - expectedClass := classUniversal - expectedTag := universalTag - - if !params.explicit && params.tag != nil { - expectedClass = classContextSpecific - expectedTag = *params.tag - } - - if !params.explicit && params.application && params.tag != nil { - expectedClass = classApplication - expectedTag = *params.tag - } - - // We have unwrapped any explicit tagging at this point. - if t.class != expectedClass || t.tag != expectedTag || t.isCompound != compoundType { - // Tags don't match. Again, it could be an optional element. - ok := setDefaultValue(v, params) - if ok { - offset = initOffset - } else { - err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)} - } - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - innerBytes := bytes[offset : offset+t.length] - offset += t.length - - // We deal with the structures defined in this package first. - switch fieldType { - case objectIdentifierType: - newSlice, err1 := parseObjectIdentifier(innerBytes) - v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice))) - if err1 == nil { - reflect.Copy(v, reflect.ValueOf(newSlice)) - } - err = err1 - return - case bitStringType: - bs, err1 := parseBitString(innerBytes) - if err1 == nil { - v.Set(reflect.ValueOf(bs)) - } - err = err1 - return - case timeType: - var time *time.Time - var err1 error - if universalTag == tagUTCTime { - time, err1 = parseUTCTime(innerBytes) - } else { - time, err1 = parseGeneralizedTime(innerBytes) - } - if err1 == nil { - v.Set(reflect.ValueOf(time)) - } - err = err1 - return - case enumeratedType: - parsedInt, err1 := parseInt(innerBytes) - if err1 == nil { - v.SetInt(int64(parsedInt)) - } - err = err1 - return - case flagType: - v.SetBool(true) - return - case bigIntType: - parsedInt := parseBigInt(innerBytes) - v.Set(reflect.ValueOf(parsedInt)) - return - } - switch val := v; val.Kind() { - case reflect.Bool: - parsedBool, err1 := parseBool(innerBytes) - if err1 == nil { - val.SetBool(parsedBool) - } - err = err1 - return - case reflect.Int, reflect.Int32: - parsedInt, err1 := parseInt(innerBytes) - if err1 == nil { - val.SetInt(int64(parsedInt)) - } - err = err1 - return - case reflect.Int64: - parsedInt, err1 := parseInt64(innerBytes) - if err1 == nil { - val.SetInt(parsedInt) - } - err = err1 - return - // TODO(dfc) Add support for the remaining integer types - case reflect.Struct: - structType := fieldType - - if structType.NumField() > 0 && - structType.Field(0).Type == rawContentsType { - bytes := bytes[initOffset:offset] - val.Field(0).Set(reflect.ValueOf(RawContent(bytes))) - } - - innerOffset := 0 - for i := 0; i < structType.NumField(); i++ { - field := structType.Field(i) - if i == 0 && field.Type == rawContentsType { - continue - } - innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1"))) - if err != nil { - return - } - } - // We allow extra bytes at the end of the SEQUENCE because - // adding elements to the end has been used in X.509 as the - // version numbers have increased. - return - case reflect.Slice: - sliceType := fieldType - if sliceType.Elem().Kind() == reflect.Uint8 { - val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes))) - reflect.Copy(val, reflect.ValueOf(innerBytes)) - return - } - newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem()) - if err1 == nil { - val.Set(newSlice) - } - err = err1 - return - case reflect.String: - var v string - switch universalTag { - case tagPrintableString: - v, err = parsePrintableString(innerBytes) - case tagIA5String: - v, err = parseIA5String(innerBytes) - case tagT61String: - v, err = parseT61String(innerBytes) - case tagUTF8String: - v, err = parseUTF8String(innerBytes) - case tagGeneralString: - // GeneralString is specified in ISO-2022/ECMA-35, - // A brief review suggests that it includes structures - // that allow the encoding to change midstring and - // such. We give up and pass it as an 8-bit string. - v, err = parseT61String(innerBytes) - default: - err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)} - } - if err == nil { - val.SetString(v) - } - return - } - err = StructuralError{"unsupported: " + v.Type().String()} - return -} - -// setDefaultValue is used to install a default value, from a tag string, into -// a Value. It is successful is the field was optional, even if a default value -// wasn't provided or it failed to install it into the Value. -func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { - if !params.optional { - return - } - ok = true - if params.defaultValue == nil { - return - } - switch val := v; val.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - val.SetInt(*params.defaultValue) - } - return -} - -// Unmarshal parses the DER-encoded ASN.1 data structure b -// and uses the reflect package to fill in an arbitrary value pointed at by val. -// Because Unmarshal uses the reflect package, the structs -// being written to must use upper case field names. -// -// An ASN.1 INTEGER can be written to an int, int32 or int64. -// If the encoded value does not fit in the Go type, -// Unmarshal returns a parse error. -// -// An ASN.1 BIT STRING can be written to a BitString. -// -// An ASN.1 OCTET STRING can be written to a []byte. -// -// An ASN.1 OBJECT IDENTIFIER can be written to an -// ObjectIdentifier. -// -// An ASN.1 ENUMERATED can be written to an Enumerated. -// -// An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a *time.Time. -// -// An ASN.1 PrintableString or IA5String can be written to a string. -// -// Any of the above ASN.1 values can be written to an interface{}. -// The value stored in the interface has the corresponding Go type. -// For integers, that type is int64. -// -// An ASN.1 SEQUENCE OF x or SET OF x can be written -// to a slice if an x can be written to the slice's element type. -// -// An ASN.1 SEQUENCE or SET can be written to a struct -// if each of the elements in the sequence can be -// written to the corresponding element in the struct. -// -// The following tags on struct fields have special meaning to Unmarshal: -// -// optional marks the field as ASN.1 OPTIONAL -// [explicit] tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC -// default:x sets the default value for optional integer fields -// -// If the type of the first field of a structure is RawContent then the raw -// ASN1 contents of the struct will be stored in it. -// -// Other ASN.1 types are not supported; if it encounters them, -// Unmarshal returns a parse error. -func Unmarshal(b []byte, val interface{}) (rest []byte, err error) { - return UnmarshalWithParams(b, val, "") -} - -// UnmarshalWithParams allows field parameters to be specified for the -// top-level element. The form of the params is the same as the field tags. -func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err error) { - v := reflect.ValueOf(val).Elem() - offset, err := parseField(v, b, 0, parseFieldParameters(params)) - if err != nil { - return nil, err - } - return b[offset:], nil -} diff --git a/libgo/go/asn1/asn1_test.go b/libgo/go/asn1/asn1_test.go deleted file mode 100644 index 1c529bd..0000000 --- a/libgo/go/asn1/asn1_test.go +++ /dev/null @@ -1,689 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package asn1 - -import ( - "bytes" - "reflect" - "testing" - "time" -) - -type int64Test struct { - in []byte - ok bool - out int64 -} - -var int64TestData = []int64Test{ - {[]byte{0x00}, true, 0}, - {[]byte{0x7f}, true, 127}, - {[]byte{0x00, 0x80}, true, 128}, - {[]byte{0x01, 0x00}, true, 256}, - {[]byte{0x80}, true, -128}, - {[]byte{0xff, 0x7f}, true, -129}, - {[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, true, -1}, - {[]byte{0xff}, true, -1}, - {[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, true, -9223372036854775808}, - {[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, false, 0}, -} - -func TestParseInt64(t *testing.T) { - for i, test := range int64TestData { - ret, err := parseInt64(test.in) - if (err == nil) != test.ok { - t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) - } - if test.ok && ret != test.out { - t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) - } - } -} - -type int32Test struct { - in []byte - ok bool - out int32 -} - -var int32TestData = []int32Test{ - {[]byte{0x00}, true, 0}, - {[]byte{0x7f}, true, 127}, - {[]byte{0x00, 0x80}, true, 128}, - {[]byte{0x01, 0x00}, true, 256}, - {[]byte{0x80}, true, -128}, - {[]byte{0xff, 0x7f}, true, -129}, - {[]byte{0xff, 0xff, 0xff, 0xff}, true, -1}, - {[]byte{0xff}, true, -1}, - {[]byte{0x80, 0x00, 0x00, 0x00}, true, -2147483648}, - {[]byte{0x80, 0x00, 0x00, 0x00, 0x00}, false, 0}, -} - -func TestParseInt32(t *testing.T) { - for i, test := range int32TestData { - ret, err := parseInt(test.in) - if (err == nil) != test.ok { - t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) - } - if test.ok && int32(ret) != test.out { - t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) - } - } -} - -var bigIntTests = []struct { - in []byte - base10 string -}{ - {[]byte{0xff}, "-1"}, - {[]byte{0x00}, "0"}, - {[]byte{0x01}, "1"}, - {[]byte{0x00, 0xff}, "255"}, - {[]byte{0xff, 0x00}, "-256"}, - {[]byte{0x01, 0x00}, "256"}, -} - -func TestParseBigInt(t *testing.T) { - for i, test := range bigIntTests { - ret := parseBigInt(test.in) - if ret.String() != test.base10 { - t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10) - } - fw := newForkableWriter() - marshalBigInt(fw, ret) - result := fw.Bytes() - if !bytes.Equal(result, test.in) { - t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in) - } - } -} - -type bitStringTest struct { - in []byte - ok bool - out []byte - bitLength int -} - -var bitStringTestData = []bitStringTest{ - {[]byte{}, false, []byte{}, 0}, - {[]byte{0x00}, true, []byte{}, 0}, - {[]byte{0x07, 0x00}, true, []byte{0x00}, 1}, - {[]byte{0x07, 0x01}, false, []byte{}, 0}, - {[]byte{0x07, 0x40}, false, []byte{}, 0}, - {[]byte{0x08, 0x00}, false, []byte{}, 0}, -} - -func TestBitString(t *testing.T) { - for i, test := range bitStringTestData { - ret, err := parseBitString(test.in) - if (err == nil) != test.ok { - t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) - } - if err == nil { - if test.bitLength != ret.BitLength || bytes.Compare(ret.Bytes, test.out) != 0 { - t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength) - } - } - } -} - -func TestBitStringAt(t *testing.T) { - bs := BitString{[]byte{0x82, 0x40}, 16} - if bs.At(0) != 1 { - t.Error("#1: Failed") - } - if bs.At(1) != 0 { - t.Error("#2: Failed") - } - if bs.At(6) != 1 { - t.Error("#3: Failed") - } - if bs.At(9) != 1 { - t.Error("#4: Failed") - } -} - -type bitStringRightAlignTest struct { - in []byte - inlen int - out []byte -} - -var bitStringRightAlignTests = []bitStringRightAlignTest{ - {[]byte{0x80}, 1, []byte{0x01}}, - {[]byte{0x80, 0x80}, 9, []byte{0x01, 0x01}}, - {[]byte{}, 0, []byte{}}, - {[]byte{0xce}, 8, []byte{0xce}}, - {[]byte{0xce, 0x47}, 16, []byte{0xce, 0x47}}, - {[]byte{0x34, 0x50}, 12, []byte{0x03, 0x45}}, -} - -func TestBitStringRightAlign(t *testing.T) { - for i, test := range bitStringRightAlignTests { - bs := BitString{test.in, test.inlen} - out := bs.RightAlign() - if bytes.Compare(out, test.out) != 0 { - t.Errorf("#%d got: %x want: %x", i, out, test.out) - } - } -} - -type objectIdentifierTest struct { - in []byte - ok bool - out []int -} - -var objectIdentifierTestData = []objectIdentifierTest{ - {[]byte{}, false, []int{}}, - {[]byte{85}, true, []int{2, 5}}, - {[]byte{85, 0x02}, true, []int{2, 5, 2}}, - {[]byte{85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}}, - {[]byte{85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}}, -} - -func TestObjectIdentifier(t *testing.T) { - for i, test := range objectIdentifierTestData { - ret, err := parseObjectIdentifier(test.in) - if (err == nil) != test.ok { - t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) - } - if err == nil { - if !reflect.DeepEqual(test.out, ret) { - t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) - } - } - } -} - -type timeTest struct { - in string - ok bool - out *time.Time -} - -var utcTestData = []timeTest{ - {"910506164540-0700", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, -7 * 60 * 60, ""}}, - {"910506164540+0730", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, 7*60*60 + 30*60, ""}}, - {"910506234540Z", true, &time.Time{1991, 05, 06, 23, 45, 40, 0, 0, "UTC"}}, - {"9105062345Z", true, &time.Time{1991, 05, 06, 23, 45, 0, 0, 0, "UTC"}}, - {"a10506234540Z", false, nil}, - {"91a506234540Z", false, nil}, - {"9105a6234540Z", false, nil}, - {"910506a34540Z", false, nil}, - {"910506334a40Z", false, nil}, - {"91050633444aZ", false, nil}, - {"910506334461Z", false, nil}, - {"910506334400Za", false, nil}, -} - -func TestUTCTime(t *testing.T) { - for i, test := range utcTestData { - ret, err := parseUTCTime([]byte(test.in)) - if (err == nil) != test.ok { - t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) - } - if err == nil { - if !reflect.DeepEqual(test.out, ret) { - t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) - } - } - } -} - -var generalizedTimeTestData = []timeTest{ - {"20100102030405Z", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, "UTC"}}, - {"20100102030405", false, nil}, - {"20100102030405+0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 6*60*60 + 7*60, ""}}, - {"20100102030405-0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, -6*60*60 - 7*60, ""}}, -} - -func TestGeneralizedTime(t *testing.T) { - for i, test := range generalizedTimeTestData { - ret, err := parseGeneralizedTime([]byte(test.in)) - if (err == nil) != test.ok { - t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) - } - if err == nil { - if !reflect.DeepEqual(test.out, ret) { - t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) - } - } - } -} - -type tagAndLengthTest struct { - in []byte - ok bool - out tagAndLength -} - -var tagAndLengthData = []tagAndLengthTest{ - {[]byte{0x80, 0x01}, true, tagAndLength{2, 0, 1, false}}, - {[]byte{0xa0, 0x01}, true, tagAndLength{2, 0, 1, true}}, - {[]byte{0x02, 0x00}, true, tagAndLength{0, 2, 0, false}}, - {[]byte{0xfe, 0x00}, true, tagAndLength{3, 30, 0, true}}, - {[]byte{0x1f, 0x01, 0x00}, true, tagAndLength{0, 1, 0, false}}, - {[]byte{0x1f, 0x81, 0x00, 0x00}, true, tagAndLength{0, 128, 0, false}}, - {[]byte{0x1f, 0x81, 0x80, 0x01, 0x00}, true, tagAndLength{0, 0x4001, 0, false}}, - {[]byte{0x00, 0x81, 0x01}, true, tagAndLength{0, 0, 1, false}}, - {[]byte{0x00, 0x82, 0x01, 0x00}, true, tagAndLength{0, 0, 256, false}}, - {[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}}, - {[]byte{0x1f, 0x85}, false, tagAndLength{}}, - {[]byte{0x30, 0x80}, false, tagAndLength{}}, -} - -func TestParseTagAndLength(t *testing.T) { - for i, test := range tagAndLengthData { - tagAndLength, _, err := parseTagAndLength(test.in, 0) - if (err == nil) != test.ok { - t.Errorf("#%d: Incorrect error result (did pass? %v, expected: %v)", i, err == nil, test.ok) - } - if err == nil && !reflect.DeepEqual(test.out, tagAndLength) { - t.Errorf("#%d: Bad result: %v (expected %v)", i, tagAndLength, test.out) - } - } -} - -type parseFieldParametersTest struct { - in string - out fieldParameters -} - -func newInt(n int) *int { return &n } - -func newInt64(n int64) *int64 { return &n } - -func newString(s string) *string { return &s } - -func newBool(b bool) *bool { return &b } - -var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{ - {"", fieldParameters{}}, - {"ia5", fieldParameters{stringType: tagIA5String}}, - {"printable", fieldParameters{stringType: tagPrintableString}}, - {"optional", fieldParameters{optional: true}}, - {"explicit", fieldParameters{explicit: true, tag: new(int)}}, - {"application", fieldParameters{application: true, tag: new(int)}}, - {"optional,explicit", fieldParameters{optional: true, explicit: true, tag: new(int)}}, - {"default:42", fieldParameters{defaultValue: newInt64(42)}}, - {"tag:17", fieldParameters{tag: newInt(17)}}, - {"optional,explicit,default:42,tag:17", fieldParameters{optional: true, explicit: true, defaultValue: newInt64(42), tag: newInt(17)}}, - {"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{true, true, false, newInt64(42), newInt(17), 0, false}}, - {"set", fieldParameters{set: true}}, -} - -func TestParseFieldParameters(t *testing.T) { - for i, test := range parseFieldParametersTestData { - f := parseFieldParameters(test.in) - if !reflect.DeepEqual(f, test.out) { - t.Errorf("#%d: Bad result: %v (expected %v)", i, f, test.out) - } - } -} - -type TestObjectIdentifierStruct struct { - OID ObjectIdentifier -} - -type TestContextSpecificTags struct { - A int `asn1:"tag:1"` -} - -type TestContextSpecificTags2 struct { - A int `asn1:"explicit,tag:1"` - B int -} - -type TestElementsAfterString struct { - S string - A, B int -} - -var unmarshalTestData = []struct { - in []byte - out interface{} -}{ - {[]byte{0x02, 0x01, 0x42}, newInt(0x42)}, - {[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}}, - {[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}}, - {[]byte{0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &[]int{1, 2, 3}}, - {[]byte{0x02, 0x01, 0x10}, newInt(16)}, - {[]byte{0x13, 0x04, 't', 'e', 's', 't'}, newString("test")}, - {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, newString("test")}, - {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, &RawValue{0, 22, false, []byte("test"), []byte("\x16\x04test")}}, - {[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}}, - {[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}}, - {[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}}, - {[]byte{0x01, 0x01, 0x00}, newBool(false)}, - {[]byte{0x01, 0x01, 0x01}, newBool(true)}, - {[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}}, -} - -func TestUnmarshal(t *testing.T) { - for i, test := range unmarshalTestData { - pv := reflect.New(reflect.TypeOf(test.out).Elem()) - val := pv.Interface() - _, err := Unmarshal(test.in, val) - if err != nil { - t.Errorf("Unmarshal failed at index %d %v", i, err) - } - if !reflect.DeepEqual(val, test.out) { - t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out) - } - } -} - -type Certificate struct { - TBSCertificate TBSCertificate - SignatureAlgorithm AlgorithmIdentifier - SignatureValue BitString -} - -type TBSCertificate struct { - Version int `asn1:"optional,explicit,default:0,tag:0"` - SerialNumber RawValue - SignatureAlgorithm AlgorithmIdentifier - Issuer RDNSequence - Validity Validity - Subject RDNSequence - PublicKey PublicKeyInfo -} - -type AlgorithmIdentifier struct { - Algorithm ObjectIdentifier -} - -type RDNSequence []RelativeDistinguishedNameSET - -type RelativeDistinguishedNameSET []AttributeTypeAndValue - -type AttributeTypeAndValue struct { - Type ObjectIdentifier - Value interface{} -} - -type Validity struct { - NotBefore, NotAfter *time.Time -} - -type PublicKeyInfo struct { - Algorithm AlgorithmIdentifier - PublicKey BitString -} - -func TestCertificate(t *testing.T) { - // This is a minimal, self-signed certificate that should parse correctly. - var cert Certificate - if _, err := Unmarshal(derEncodedSelfSignedCertBytes, &cert); err != nil { - t.Errorf("Unmarshal failed: %v", err) - } - if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) { - t.Errorf("Bad result:\ngot: %+v\nwant: %+v", cert, derEncodedSelfSignedCert) - } -} - -func TestCertificateWithNUL(t *testing.T) { - // This is the paypal NUL-hack certificate. It should fail to parse because - // NUL isn't a permitted character in a PrintableString. - - var cert Certificate - if _, err := Unmarshal(derEncodedPaypalNULCertBytes, &cert); err == nil { - t.Error("Unmarshal succeeded, should not have") - } -} - -type rawStructTest struct { - Raw RawContent - A int -} - -func TestRawStructs(t *testing.T) { - var s rawStructTest - input := []byte{0x30, 0x03, 0x02, 0x01, 0x50} - - rest, err := Unmarshal(input, &s) - if len(rest) != 0 { - t.Errorf("incomplete parse: %x", rest) - return - } - if err != nil { - t.Error(err) - return - } - if s.A != 0x50 { - t.Errorf("bad value for A: got %d want %d", s.A, 0x50) - } - if bytes.Compare([]byte(s.Raw), input) != 0 { - t.Errorf("bad value for Raw: got %x want %x", s.Raw, input) - } -} - -var derEncodedSelfSignedCert = Certificate{ - TBSCertificate: TBSCertificate{ - Version: 0, - SerialNumber: RawValue{Class: 0, Tag: 2, IsCompound: false, Bytes: []uint8{0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}, FullBytes: []byte{2, 9, 0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}}, - SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}}, - Issuer: RDNSequence{ - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, - }, - Validity: Validity{NotBefore: &time.Time{Year: 2009, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, ZoneOffset: 0, Zone: "UTC"}, NotAfter: &time.Time{Year: 2010, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, ZoneOffset: 0, Zone: "UTC"}}, - Subject: RDNSequence{ - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, - }, - PublicKey: PublicKeyInfo{ - Algorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}}, - PublicKey: BitString{ - Bytes: []uint8{ - 0x30, 0x48, 0x2, 0x41, 0x0, 0xcd, 0xb7, - 0x63, 0x9c, 0x32, 0x78, 0xf0, 0x6, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, - 0x90, 0x2b, 0x59, 0x2d, 0x8c, 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, - 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, - 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, 0x96, 0x57, 0x72, 0x2a, 0x4f, - 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, 0xdc, 0x8f, 0xde, 0xec, - 0x35, 0x7d, 0x2, 0x3, 0x1, 0x0, 0x1, - }, - BitLength: 592, - }, - }, - }, - SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}}, - SignatureValue: BitString{ - Bytes: []uint8{ - 0xa6, 0x7b, 0x6, 0xec, 0x5e, 0xce, - 0x92, 0x77, 0x2c, 0xa4, 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, - 0x7b, 0x45, 0x11, 0xcd, 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x4, 0x2, 0xdf, 0x2b, - 0x99, 0x8b, 0xb9, 0xa4, 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, - 0xd9, 0x1e, 0xde, 0x14, 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, - 0xfa, 0x88, 0x21, 0x49, 0x4, 0x35, - }, - BitLength: 512, - }, -} - -var derEncodedSelfSignedCertBytes = []byte{ - 0x30, 0x82, 0x02, 0x18, 0x30, - 0x82, 0x01, 0xc2, 0x02, 0x09, 0x00, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, - 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, - 0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, - 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, - 0x73, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, - 0x30, 0x39, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, 0x33, 0x5a, - 0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, - 0x33, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, 0x69, - 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, - 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x1a, - 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, 0x73, - 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, - 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xcd, 0xb7, 0x63, 0x9c, 0x32, 0x78, - 0xf0, 0x06, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, 0x90, 0x2b, 0x59, 0x2d, 0x8c, - 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, - 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, - 0x96, 0x57, 0x72, 0x2a, 0x4f, 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, - 0xdc, 0x8f, 0xde, 0xec, 0x35, 0x7d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, - 0x03, 0x41, 0x00, 0xa6, 0x7b, 0x06, 0xec, 0x5e, 0xce, 0x92, 0x77, 0x2c, 0xa4, - 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, 0x7b, 0x45, 0x11, 0xcd, - 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x04, 0x02, 0xdf, 0x2b, 0x99, 0x8b, 0xb9, 0xa4, - 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, 0xd9, 0x1e, 0xde, 0x14, - 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, 0xfa, 0x88, 0x21, 0x49, - 0x04, 0x35, -} - -var derEncodedPaypalNULCertBytes = []byte{ - 0x30, 0x82, 0x06, 0x44, 0x30, - 0x82, 0x05, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x00, 0xf0, 0x9b, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x30, 0x82, 0x01, 0x12, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x09, 0x42, 0x61, 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, - 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x42, 0x61, - 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x50, 0x53, 0x20, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x73, 0x2e, 0x6c, 0x2e, 0x31, 0x2e, - 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x25, 0x67, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, - 0x20, 0x43, 0x2e, 0x49, 0x2e, 0x46, 0x2e, 0x20, 0x20, 0x42, 0x2d, 0x42, 0x36, - 0x32, 0x32, 0x31, 0x30, 0x36, 0x39, 0x35, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x13, 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, - 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, - 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, - 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, - 0x01, 0x16, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, - 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39, - 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, 0x17, 0x0d, - 0x31, 0x31, 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, - 0x30, 0x81, 0x94, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, - 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x53, 0x61, 0x6e, 0x20, - 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x31, 0x11, 0x30, 0x0f, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, - 0x74, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b, - 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x31, 0x2f, - 0x30, 0x2d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x26, 0x77, 0x77, 0x77, 0x2e, - 0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x73, 0x73, - 0x6c, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x63, 0x30, 0x81, 0x9f, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, - 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x69, - 0xfa, 0x6f, 0x3a, 0x00, 0xb4, 0x21, 0x1b, 0xc8, 0xb1, 0x02, 0xd7, 0x3f, 0x19, - 0xb2, 0xc4, 0x6d, 0xb4, 0x54, 0xf8, 0x8b, 0x8a, 0xcc, 0xdb, 0x72, 0xc2, 0x9e, - 0x3c, 0x60, 0xb9, 0xc6, 0x91, 0x3d, 0x82, 0xb7, 0x7d, 0x99, 0xff, 0xd1, 0x29, - 0x84, 0xc1, 0x73, 0x53, 0x9c, 0x82, 0xdd, 0xfc, 0x24, 0x8c, 0x77, 0xd5, 0x41, - 0xf3, 0xe8, 0x1e, 0x42, 0xa1, 0xad, 0x2d, 0x9e, 0xff, 0x5b, 0x10, 0x26, 0xce, - 0x9d, 0x57, 0x17, 0x73, 0x16, 0x23, 0x38, 0xc8, 0xd6, 0xf1, 0xba, 0xa3, 0x96, - 0x5b, 0x16, 0x67, 0x4a, 0x4f, 0x73, 0x97, 0x3a, 0x4d, 0x14, 0xa4, 0xf4, 0xe2, - 0x3f, 0x8b, 0x05, 0x83, 0x42, 0xd1, 0xd0, 0xdc, 0x2f, 0x7a, 0xe5, 0xb6, 0x10, - 0xb2, 0x11, 0xc0, 0xdc, 0x21, 0x2a, 0x90, 0xff, 0xae, 0x97, 0x71, 0x5a, 0x49, - 0x81, 0xac, 0x40, 0xf3, 0x3b, 0xb8, 0x59, 0xb2, 0x4f, 0x02, 0x03, 0x01, 0x00, - 0x01, 0xa3, 0x82, 0x03, 0x21, 0x30, 0x82, 0x03, 0x1d, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40, - 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03, 0xf8, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, - 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1d, 0x06, 0x03, 0x55, - 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x61, 0x8f, 0x61, 0x34, 0x43, 0x55, 0x14, - 0x7f, 0x27, 0x09, 0xce, 0x4c, 0x8b, 0xea, 0x9b, 0x7b, 0x19, 0x25, 0xbc, 0x6e, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, - 0x0e, 0x07, 0x60, 0xd4, 0x39, 0xc9, 0x1b, 0x5b, 0x5d, 0x90, 0x7b, 0x23, 0xc8, - 0xd2, 0x34, 0x9d, 0x4a, 0x9a, 0x46, 0x39, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, - 0x11, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x1d, 0x12, 0x04, - 0x15, 0x30, 0x13, 0x81, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, - 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x72, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x65, 0x16, 0x63, - 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e, - 0x4f, 0x54, 0x20, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x44, 0x2e, - 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68, - 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, - 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x2f, 0x06, 0x09, 0x60, - 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x02, 0x04, 0x22, 0x16, 0x20, 0x68, - 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, - 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, - 0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, - 0x86, 0xf8, 0x42, 0x01, 0x04, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, - 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, - 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, - 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x46, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x03, 0x04, 0x39, 0x16, 0x37, - 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, - 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, - 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, - 0x6d, 0x6c, 0x3f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, - 0x42, 0x01, 0x07, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, - 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, - 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, - 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x30, 0x41, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x34, 0x16, 0x32, 0x68, 0x74, - 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, - 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, - 0x30, 0x30, 0x32, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x4c, 0x41, - 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x30, 0x81, 0x83, 0x06, - 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x7c, 0x30, 0x7a, 0x30, 0x39, 0xa0, 0x37, 0xa0, - 0x35, 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, - 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, - 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, - 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, - 0x72, 0x6c, 0x30, 0x3d, 0xa0, 0x3b, 0xa0, 0x39, 0x86, 0x37, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x69, - 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, - 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, - 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, - 0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, - 0x26, 0x30, 0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, - 0x73, 0x70, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x68, 0xee, 0x79, 0x97, 0x97, 0xdd, 0x3b, - 0xef, 0x16, 0x6a, 0x06, 0xf2, 0x14, 0x9a, 0x6e, 0xcd, 0x9e, 0x12, 0xf7, 0xaa, - 0x83, 0x10, 0xbd, 0xd1, 0x7c, 0x98, 0xfa, 0xc7, 0xae, 0xd4, 0x0e, 0x2c, 0x9e, - 0x38, 0x05, 0x9d, 0x52, 0x60, 0xa9, 0x99, 0x0a, 0x81, 0xb4, 0x98, 0x90, 0x1d, - 0xae, 0xbb, 0x4a, 0xd7, 0xb9, 0xdc, 0x88, 0x9e, 0x37, 0x78, 0x41, 0x5b, 0xf7, - 0x82, 0xa5, 0xf2, 0xba, 0x41, 0x25, 0x5a, 0x90, 0x1a, 0x1e, 0x45, 0x38, 0xa1, - 0x52, 0x58, 0x75, 0x94, 0x26, 0x44, 0xfb, 0x20, 0x07, 0xba, 0x44, 0xcc, 0xe5, - 0x4a, 0x2d, 0x72, 0x3f, 0x98, 0x47, 0xf6, 0x26, 0xdc, 0x05, 0x46, 0x05, 0x07, - 0x63, 0x21, 0xab, 0x46, 0x9b, 0x9c, 0x78, 0xd5, 0x54, 0x5b, 0x3d, 0x0c, 0x1e, - 0xc8, 0x64, 0x8c, 0xb5, 0x50, 0x23, 0x82, 0x6f, 0xdb, 0xb8, 0x22, 0x1c, 0x43, - 0x96, 0x07, 0xa8, 0xbb, -} diff --git a/libgo/go/asn1/common.go b/libgo/go/asn1/common.go deleted file mode 100644 index 01f4f7b..0000000 --- a/libgo/go/asn1/common.go +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package asn1 - -import ( - "reflect" - "strconv" - "strings" -) - -// ASN.1 objects have metadata preceding them: -// the tag: the type of the object -// a flag denoting if this object is compound or not -// the class type: the namespace of the tag -// the length of the object, in bytes - -// Here are some standard tags and classes - -const ( - tagBoolean = 1 - tagInteger = 2 - tagBitString = 3 - tagOctetString = 4 - tagOID = 6 - tagEnum = 10 - tagUTF8String = 12 - tagSequence = 16 - tagSet = 17 - tagPrintableString = 19 - tagT61String = 20 - tagIA5String = 22 - tagUTCTime = 23 - tagGeneralizedTime = 24 - tagGeneralString = 27 -) - -const ( - classUniversal = 0 - classApplication = 1 - classContextSpecific = 2 - classPrivate = 3 -) - -type tagAndLength struct { - class, tag, length int - isCompound bool -} - -// ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead -// of" and "in addition to". When not specified, every primitive type has a -// default tag in the UNIVERSAL class. -// -// For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1 -// doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT -// CONTEXT-SPECIFIC 42], that means that the tag is replaced by another. -// -// On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an -// /additional/ tag would wrap the default tag. This explicit tag will have the -// compound flag set. -// -// (This is used in order to remove ambiguity with optional elements.) -// -// You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we -// don't support that here. We support a single layer of EXPLICIT or IMPLICIT -// tagging with tag strings on the fields of a structure. - -// fieldParameters is the parsed representation of tag string from a structure field. -type fieldParameters struct { - optional bool // true iff the field is OPTIONAL - explicit bool // true iff an EXPLICIT tag is in use. - application bool // true iff an APPLICATION tag is in use. - defaultValue *int64 // a default value for INTEGER typed fields (maybe nil). - tag *int // the EXPLICIT or IMPLICIT tag (maybe nil). - stringType int // the string tag to use when marshaling. - set bool // true iff this should be encoded as a SET - - // Invariants: - // if explicit is set, tag is non-nil. -} - -// Given a tag string with the format specified in the package comment, -// parseFieldParameters will parse it into a fieldParameters structure, -// ignoring unknown parts of the string. -func parseFieldParameters(str string) (ret fieldParameters) { - for _, part := range strings.Split(str, ",") { - switch { - case part == "optional": - ret.optional = true - case part == "explicit": - ret.explicit = true - if ret.tag == nil { - ret.tag = new(int) - } - case part == "ia5": - ret.stringType = tagIA5String - case part == "printable": - ret.stringType = tagPrintableString - case strings.HasPrefix(part, "default:"): - i, err := strconv.Atoi64(part[8:]) - if err == nil { - ret.defaultValue = new(int64) - *ret.defaultValue = i - } - case strings.HasPrefix(part, "tag:"): - i, err := strconv.Atoi(part[4:]) - if err == nil { - ret.tag = new(int) - *ret.tag = i - } - case part == "set": - ret.set = true - case part == "application": - ret.application = true - if ret.tag == nil { - ret.tag = new(int) - } - } - } - return -} - -// Given a reflected Go type, getUniversalType returns the default tag number -// and expected compound flag. -func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) { - switch t { - case objectIdentifierType: - return tagOID, false, true - case bitStringType: - return tagBitString, false, true - case timeType: - return tagUTCTime, false, true - case enumeratedType: - return tagEnum, false, true - case bigIntType: - return tagInteger, false, true - } - switch t.Kind() { - case reflect.Bool: - return tagBoolean, false, true - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return tagInteger, false, true - case reflect.Struct: - return tagSequence, true, true - case reflect.Slice: - if t.Elem().Kind() == reflect.Uint8 { - return tagOctetString, false, true - } - if strings.HasSuffix(t.Name(), "SET") { - return tagSet, true, true - } - return tagSequence, true, true - case reflect.String: - return tagPrintableString, false, true - } - return 0, false, false -} diff --git a/libgo/go/asn1/marshal.go b/libgo/go/asn1/marshal.go deleted file mode 100644 index 583d010..0000000 --- a/libgo/go/asn1/marshal.go +++ /dev/null @@ -1,547 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package asn1 - -import ( - "big" - "bytes" - "fmt" - "io" - "reflect" - "time" -) - -// A forkableWriter is an in-memory buffer that can be -// 'forked' to create new forkableWriters that bracket the -// original. After -// pre, post := w.fork(); -// the overall sequence of bytes represented is logically w+pre+post. -type forkableWriter struct { - *bytes.Buffer - pre, post *forkableWriter -} - -func newForkableWriter() *forkableWriter { - return &forkableWriter{bytes.NewBuffer(nil), nil, nil} -} - -func (f *forkableWriter) fork() (pre, post *forkableWriter) { - if f.pre != nil || f.post != nil { - panic("have already forked") - } - f.pre = newForkableWriter() - f.post = newForkableWriter() - return f.pre, f.post -} - -func (f *forkableWriter) Len() (l int) { - l += f.Buffer.Len() - if f.pre != nil { - l += f.pre.Len() - } - if f.post != nil { - l += f.post.Len() - } - return -} - -func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) { - n, err = out.Write(f.Bytes()) - if err != nil { - return - } - - var nn int - - if f.pre != nil { - nn, err = f.pre.writeTo(out) - n += nn - if err != nil { - return - } - } - - if f.post != nil { - nn, err = f.post.writeTo(out) - n += nn - } - return -} - -func marshalBase128Int(out *forkableWriter, n int64) (err error) { - if n == 0 { - err = out.WriteByte(0) - return - } - - l := 0 - for i := n; i > 0; i >>= 7 { - l++ - } - - for i := l - 1; i >= 0; i-- { - o := byte(n >> uint(i*7)) - o &= 0x7f - if i != 0 { - o |= 0x80 - } - err = out.WriteByte(o) - if err != nil { - return - } - } - - return nil -} - -func marshalInt64(out *forkableWriter, i int64) (err error) { - n := int64Length(i) - - for ; n > 0; n-- { - err = out.WriteByte(byte(i >> uint((n-1)*8))) - if err != nil { - return - } - } - - return nil -} - -func int64Length(i int64) (numBytes int) { - numBytes = 1 - - for i > 127 { - numBytes++ - i >>= 8 - } - - for i < -128 { - numBytes++ - i >>= 8 - } - - return -} - -func marshalBigInt(out *forkableWriter, n *big.Int) (err error) { - if n.Sign() < 0 { - // A negative number has to be converted to two's-complement - // form. So we'll subtract 1 and invert. If the - // most-significant-bit isn't set then we'll need to pad the - // beginning with 0xff in order to keep the number negative. - nMinus1 := new(big.Int).Neg(n) - nMinus1.Sub(nMinus1, bigOne) - bytes := nMinus1.Bytes() - for i := range bytes { - bytes[i] ^= 0xff - } - if len(bytes) == 0 || bytes[0]&0x80 == 0 { - err = out.WriteByte(0xff) - if err != nil { - return - } - } - _, err = out.Write(bytes) - } else if n.Sign() == 0 { - // Zero is written as a single 0 zero rather than no bytes. - err = out.WriteByte(0x00) - } else { - bytes := n.Bytes() - if len(bytes) > 0 && bytes[0]&0x80 != 0 { - // We'll have to pad this with 0x00 in order to stop it - // looking like a negative number. - err = out.WriteByte(0) - if err != nil { - return - } - } - _, err = out.Write(bytes) - } - return -} - -func marshalLength(out *forkableWriter, i int) (err error) { - n := lengthLength(i) - - for ; n > 0; n-- { - err = out.WriteByte(byte(i >> uint((n-1)*8))) - if err != nil { - return - } - } - - return nil -} - -func lengthLength(i int) (numBytes int) { - numBytes = 1 - for i > 255 { - numBytes++ - i >>= 8 - } - return -} - -func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) { - b := uint8(t.class) << 6 - if t.isCompound { - b |= 0x20 - } - if t.tag >= 31 { - b |= 0x1f - err = out.WriteByte(b) - if err != nil { - return - } - err = marshalBase128Int(out, int64(t.tag)) - if err != nil { - return - } - } else { - b |= uint8(t.tag) - err = out.WriteByte(b) - if err != nil { - return - } - } - - if t.length >= 128 { - l := lengthLength(t.length) - err = out.WriteByte(0x80 | byte(l)) - if err != nil { - return - } - err = marshalLength(out, t.length) - if err != nil { - return - } - } else { - err = out.WriteByte(byte(t.length)) - if err != nil { - return - } - } - - return nil -} - -func marshalBitString(out *forkableWriter, b BitString) (err error) { - paddingBits := byte((8 - b.BitLength%8) % 8) - err = out.WriteByte(paddingBits) - if err != nil { - return - } - _, err = out.Write(b.Bytes) - return -} - -func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) { - if len(oid) < 2 || oid[0] > 6 || oid[1] >= 40 { - return StructuralError{"invalid object identifier"} - } - - err = out.WriteByte(byte(oid[0]*40 + oid[1])) - if err != nil { - return - } - for i := 2; i < len(oid); i++ { - err = marshalBase128Int(out, int64(oid[i])) - if err != nil { - return - } - } - - return -} - -func marshalPrintableString(out *forkableWriter, s string) (err error) { - b := []byte(s) - for _, c := range b { - if !isPrintable(c) { - return StructuralError{"PrintableString contains invalid character"} - } - } - - _, err = out.Write(b) - return -} - -func marshalIA5String(out *forkableWriter, s string) (err error) { - b := []byte(s) - for _, c := range b { - if c > 127 { - return StructuralError{"IA5String contains invalid character"} - } - } - - _, err = out.Write(b) - return -} - -func marshalTwoDigits(out *forkableWriter, v int) (err error) { - err = out.WriteByte(byte('0' + (v/10)%10)) - if err != nil { - return - } - return out.WriteByte(byte('0' + v%10)) -} - -func marshalUTCTime(out *forkableWriter, t *time.Time) (err error) { - switch { - case 1950 <= t.Year && t.Year < 2000: - err = marshalTwoDigits(out, int(t.Year-1900)) - case 2000 <= t.Year && t.Year < 2050: - err = marshalTwoDigits(out, int(t.Year-2000)) - default: - return StructuralError{"Cannot represent time as UTCTime"} - } - - if err != nil { - return - } - - err = marshalTwoDigits(out, t.Month) - if err != nil { - return - } - - err = marshalTwoDigits(out, t.Day) - if err != nil { - return - } - - err = marshalTwoDigits(out, t.Hour) - if err != nil { - return - } - - err = marshalTwoDigits(out, t.Minute) - if err != nil { - return - } - - err = marshalTwoDigits(out, t.Second) - if err != nil { - return - } - - switch { - case t.ZoneOffset/60 == 0: - err = out.WriteByte('Z') - return - case t.ZoneOffset > 0: - err = out.WriteByte('+') - case t.ZoneOffset < 0: - err = out.WriteByte('-') - } - - if err != nil { - return - } - - offsetMinutes := t.ZoneOffset / 60 - if offsetMinutes < 0 { - offsetMinutes = -offsetMinutes - } - - err = marshalTwoDigits(out, offsetMinutes/60) - if err != nil { - return - } - - err = marshalTwoDigits(out, offsetMinutes%60) - return -} - -func stripTagAndLength(in []byte) []byte { - _, offset, err := parseTagAndLength(in, 0) - if err != nil { - return in - } - return in[offset:] -} - -func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) { - switch value.Type() { - case timeType: - return marshalUTCTime(out, value.Interface().(*time.Time)) - case bitStringType: - return marshalBitString(out, value.Interface().(BitString)) - case objectIdentifierType: - return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier)) - case bigIntType: - return marshalBigInt(out, value.Interface().(*big.Int)) - } - - switch v := value; v.Kind() { - case reflect.Bool: - if v.Bool() { - return out.WriteByte(255) - } else { - return out.WriteByte(0) - } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return marshalInt64(out, int64(v.Int())) - case reflect.Struct: - t := v.Type() - - startingField := 0 - - // If the first element of the structure is a non-empty - // RawContents, then we don't bother serializing the rest. - if t.NumField() > 0 && t.Field(0).Type == rawContentsType { - s := v.Field(0) - if s.Len() > 0 { - bytes := make([]byte, s.Len()) - for i := 0; i < s.Len(); i++ { - bytes[i] = uint8(s.Index(i).Uint()) - } - /* The RawContents will contain the tag and - * length fields but we'll also be writing - * those ourselves, so we strip them out of - * bytes */ - _, err = out.Write(stripTagAndLength(bytes)) - return - } else { - startingField = 1 - } - } - - for i := startingField; i < t.NumField(); i++ { - var pre *forkableWriter - pre, out = out.fork() - err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1"))) - if err != nil { - return - } - } - return - case reflect.Slice: - sliceType := v.Type() - if sliceType.Elem().Kind() == reflect.Uint8 { - bytes := make([]byte, v.Len()) - for i := 0; i < v.Len(); i++ { - bytes[i] = uint8(v.Index(i).Uint()) - } - _, err = out.Write(bytes) - return - } - - var params fieldParameters - for i := 0; i < v.Len(); i++ { - var pre *forkableWriter - pre, out = out.fork() - err = marshalField(pre, v.Index(i), params) - if err != nil { - return - } - } - return - case reflect.String: - if params.stringType == tagIA5String { - return marshalIA5String(out, v.String()) - } else { - return marshalPrintableString(out, v.String()) - } - return - } - - return StructuralError{"unknown Go type"} -} - -func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) { - // If the field is an interface{} then recurse into it. - if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { - return marshalField(out, v.Elem(), params) - } - - if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { - return - } - - if v.Type() == rawValueType { - rv := v.Interface().(RawValue) - if len(rv.FullBytes) != 0 { - _, err = out.Write(rv.FullBytes) - } else { - err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}) - if err != nil { - return - } - _, err = out.Write(rv.Bytes) - } - return - } - - tag, isCompound, ok := getUniversalType(v.Type()) - if !ok { - err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} - return - } - class := classUniversal - - if params.stringType != 0 { - if tag != tagPrintableString { - return StructuralError{"Explicit string type given to non-string member"} - } - tag = params.stringType - } - - if params.set { - if tag != tagSequence { - return StructuralError{"Non sequence tagged as set"} - } - tag = tagSet - } - - tags, body := out.fork() - - err = marshalBody(body, v, params) - if err != nil { - return - } - - bodyLen := body.Len() - - var explicitTag *forkableWriter - if params.explicit { - explicitTag, tags = tags.fork() - } - - if !params.explicit && params.tag != nil { - // implicit tag. - tag = *params.tag - class = classContextSpecific - } - - err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound}) - if err != nil { - return - } - - if params.explicit { - err = marshalTagAndLength(explicitTag, tagAndLength{ - class: classContextSpecific, - tag: *params.tag, - length: bodyLen + tags.Len(), - isCompound: true, - }) - } - - return nil -} - -// Marshal returns the ASN.1 encoding of val. -func Marshal(val interface{}) ([]byte, error) { - var out bytes.Buffer - v := reflect.ValueOf(val) - f := newForkableWriter() - err := marshalField(f, v, fieldParameters{}) - if err != nil { - return nil, err - } - _, err = f.writeTo(&out) - return out.Bytes(), nil -} diff --git a/libgo/go/asn1/marshal_test.go b/libgo/go/asn1/marshal_test.go deleted file mode 100644 index 03df5f1..0000000 --- a/libgo/go/asn1/marshal_test.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package asn1 - -import ( - "bytes" - "encoding/hex" - "testing" - "time" -) - -type intStruct struct { - A int -} - -type twoIntStruct struct { - A int - B int -} - -type nestedStruct struct { - A intStruct -} - -type rawContentsStruct struct { - Raw RawContent - A int -} - -type implicitTagTest struct { - A int `asn1:"implicit,tag:5"` -} - -type explicitTagTest struct { - A int `asn1:"explicit,tag:5"` -} - -type ia5StringTest struct { - A string `asn1:"ia5"` -} - -type printableStringTest struct { - A string `asn1:"printable"` -} - -type optionalRawValueTest struct { - A RawValue `asn1:"optional"` -} - -type testSET []int - -func setPST(t *time.Time) *time.Time { - t.ZoneOffset = -28800 - return t -} - -type marshalTest struct { - in interface{} - out string // hex encoded -} - -var marshalTests = []marshalTest{ - {10, "02010a"}, - {127, "02017f"}, - {128, "02020080"}, - {-128, "020180"}, - {-129, "0202ff7f"}, - {intStruct{64}, "3003020140"}, - {twoIntStruct{64, 65}, "3006020140020141"}, - {nestedStruct{intStruct{127}}, "3005300302017f"}, - {[]byte{1, 2, 3}, "0403010203"}, - {implicitTagTest{64}, "3003850140"}, - {explicitTagTest{64}, "3005a503020140"}, - {time.SecondsToUTC(0), "170d3730303130313030303030305a"}, - {time.SecondsToUTC(1258325776), "170d3039313131353232353631365a"}, - {setPST(time.SecondsToUTC(1258325776)), "17113039313131353232353631362d30383030"}, - {BitString{[]byte{0x80}, 1}, "03020780"}, - {BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"}, - {ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"}, - {ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"}, - {"test", "130474657374"}, - { - "" + - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 127 times 'x' - "137f" + - "7878787878787878787878787878787878787878787878787878787878787878" + - "7878787878787878787878787878787878787878787878787878787878787878" + - "7878787878787878787878787878787878787878787878787878787878787878" + - "78787878787878787878787878787878787878787878787878787878787878", - }, - { - "" + - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 128 times 'x' - "138180" + - "7878787878787878787878787878787878787878787878787878787878787878" + - "7878787878787878787878787878787878787878787878787878787878787878" + - "7878787878787878787878787878787878787878787878787878787878787878" + - "7878787878787878787878787878787878787878787878787878787878787878", - }, - {ia5StringTest{"test"}, "3006160474657374"}, - {optionalRawValueTest{}, "3000"}, - {printableStringTest{"test"}, "3006130474657374"}, - {printableStringTest{"test*"}, "30071305746573742a"}, - {rawContentsStruct{nil, 64}, "3003020140"}, - {rawContentsStruct{[]byte{0x30, 3, 1, 2, 3}, 64}, "3003010203"}, - {RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"}, - {testSET([]int{10}), "310302010a"}, -} - -func TestMarshal(t *testing.T) { - for i, test := range marshalTests { - data, err := Marshal(test.in) - if err != nil { - t.Errorf("#%d failed: %s", i, err) - } - out, _ := hex.DecodeString(test.out) - if bytes.Compare(out, data) != 0 { - t.Errorf("#%d got: %x want %x", i, data, out) - } - } -} diff --git a/libgo/go/big/arith.go b/libgo/go/big/arith.go deleted file mode 100644 index 242bd1e..0000000 --- a/libgo/go/big/arith.go +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file provides Go implementations of elementary multi-precision -// arithmetic operations on word vectors. Needed for platforms without -// assembly implementations of these routines. - -package big - -// TODO(gri) Decide if Word needs to remain exported. - -type Word uintptr - -const ( - // Compute the size _S of a Word in bytes. - _m = ^Word(0) - _logS = _m>>8&1 + _m>>16&1 + _m>>32&1 - _S = 1 << _logS - - _W = _S << 3 // word size in bits - _B = 1 << _W // digit base - _M = _B - 1 // digit mask - - _W2 = _W / 2 // half word size in bits - _B2 = 1 << _W2 // half digit base - _M2 = _B2 - 1 // half digit mask -) - -// ---------------------------------------------------------------------------- -// Elementary operations on words -// -// These operations are used by the vector operations below. - -// z1<<_W + z0 = x+y+c, with c == 0 or 1 -func addWW_g(x, y, c Word) (z1, z0 Word) { - yc := y + c - z0 = x + yc - if z0 < x || yc < y { - z1 = 1 - } - return -} - -// z1<<_W + z0 = x-y-c, with c == 0 or 1 -func subWW_g(x, y, c Word) (z1, z0 Word) { - yc := y + c - z0 = x - yc - if z0 > x || yc < y { - z1 = 1 - } - return -} - -// z1<<_W + z0 = x*y -func mulWW(x, y Word) (z1, z0 Word) { return mulWW_g(x, y) } -// Adapted from Warren, Hacker's Delight, p. 132. -func mulWW_g(x, y Word) (z1, z0 Word) { - x0 := x & _M2 - x1 := x >> _W2 - y0 := y & _M2 - y1 := y >> _W2 - w0 := x0 * y0 - t := x1*y0 + w0>>_W2 - w1 := t & _M2 - w2 := t >> _W2 - w1 += x0 * y1 - z1 = x1*y1 + w2 + w1>>_W2 - z0 = x * y - return -} - -// z1<<_W + z0 = x*y + c -func mulAddWWW_g(x, y, c Word) (z1, z0 Word) { - z1, zz0 := mulWW(x, y) - if z0 = zz0 + c; z0 < zz0 { - z1++ - } - return -} - -// Length of x in bits. -func bitLen(x Word) (n int) { - for ; x >= 0x100; x >>= 8 { - n += 8 - } - for ; x > 0; x >>= 1 { - n++ - } - return -} - -// log2 computes the integer binary logarithm of x. -// The result is the integer n for which 2^n <= x < 2^(n+1). -// If x == 0, the result is -1. -func log2(x Word) int { - return bitLen(x) - 1 -} - -// Number of leading zeros in x. -func leadingZeros(x Word) uint { - return uint(_W - bitLen(x)) -} - -// q = (u1<<_W + u0 - r)/y -func divWW(x1, x0, y Word) (q, r Word) { return divWW_g(x1, x0, y) } -// Adapted from Warren, Hacker's Delight, p. 152. -func divWW_g(u1, u0, v Word) (q, r Word) { - if u1 >= v { - return 1<<_W - 1, 1<<_W - 1 - } - - s := leadingZeros(v) - v <<= s - - vn1 := v >> _W2 - vn0 := v & _M2 - un32 := u1<>(_W-s) - un10 := u0 << s - un1 := un10 >> _W2 - un0 := un10 & _M2 - q1 := un32 / vn1 - rhat := un32 - q1*vn1 - -again1: - if q1 >= _B2 || q1*vn0 > _B2*rhat+un1 { - q1-- - rhat += vn1 - if rhat < _B2 { - goto again1 - } - } - - un21 := un32*_B2 + un1 - q1*v - q0 := un21 / vn1 - rhat = un21 - q0*vn1 - -again2: - if q0 >= _B2 || q0*vn0 > _B2*rhat+un0 { - q0-- - rhat += vn1 - if rhat < _B2 { - goto again2 - } - } - - return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s -} - -func addVV(z, x, y []Word) (c Word) { return addVV_g(z, x, y) } -func addVV_g(z, x, y []Word) (c Word) { - for i := range z { - c, z[i] = addWW_g(x[i], y[i], c) - } - return -} - -func subVV(z, x, y []Word) (c Word) { return subVV_g(z, x, y) } -func subVV_g(z, x, y []Word) (c Word) { - for i := range z { - c, z[i] = subWW_g(x[i], y[i], c) - } - return -} - -func addVW(z, x []Word, y Word) (c Word) { return addVW_g(z, x, y) } -func addVW_g(z, x []Word, y Word) (c Word) { - c = y - for i := range z { - c, z[i] = addWW_g(x[i], c, 0) - } - return -} - -func subVW(z, x []Word, y Word) (c Word) { return subVW_g(z, x, y) } -func subVW_g(z, x []Word, y Word) (c Word) { - c = y - for i := range z { - c, z[i] = subWW_g(x[i], c, 0) - } - return -} - -func shlVU(z, x []Word, s uint) (c Word) { return shlVU_g(z, x, s) } -func shlVU_g(z, x []Word, s uint) (c Word) { - if n := len(z); n > 0 { - ŝ := _W - s - w1 := x[n-1] - c = w1 >> ŝ - for i := n - 1; i > 0; i-- { - w := w1 - w1 = x[i-1] - z[i] = w<>ŝ - } - z[0] = w1 << s - } - return -} - -func shrVU(z, x []Word, s uint) (c Word) { return shrVU_g(z, x, s) } -func shrVU_g(z, x []Word, s uint) (c Word) { - if n := len(z); n > 0 { - ŝ := _W - s - w1 := x[0] - c = w1 << ŝ - for i := 0; i < n-1; i++ { - w := w1 - w1 = x[i+1] - z[i] = w>>s | w1<<ŝ - } - z[n-1] = w1 >> s - } - return -} - -func mulAddVWW(z, x []Word, y, r Word) (c Word) { return mulAddVWW_g(z, x, y, r) } -func mulAddVWW_g(z, x []Word, y, r Word) (c Word) { - c = r - for i := range z { - c, z[i] = mulAddWWW_g(x[i], y, c) - } - return -} - -func addMulVVW(z, x []Word, y Word) (c Word) { return addMulVVW_g(z, x, y) } -func addMulVVW_g(z, x []Word, y Word) (c Word) { - for i := range z { - z1, z0 := mulAddWWW_g(x[i], y, z[i]) - c, z[i] = addWW_g(z0, c, 0) - c += z1 - } - return -} - -func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) { return divWVW_g(z, xn, x, y) } -func divWVW_g(z []Word, xn Word, x []Word, y Word) (r Word) { - r = xn - for i := len(z) - 1; i >= 0; i-- { - z[i], r = divWW_g(r, x[i], y) - } - return -} diff --git a/libgo/go/big/arith_decl.go b/libgo/go/big/arith_decl.go deleted file mode 100644 index 95fcd8b..0000000 --- a/libgo/go/big/arith_decl.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package big - -// implemented in arith_$GOARCH.s -func mulWW(x, y Word) (z1, z0 Word) -func divWW(x1, x0, y Word) (q, r Word) -func addVV(z, x, y []Word) (c Word) -func subVV(z, x, y []Word) (c Word) -func addVW(z, x []Word, y Word) (c Word) -func subVW(z, x []Word, y Word) (c Word) -func shlVU(z, x []Word, s uint) (c Word) -func shrVU(z, x []Word, s uint) (c Word) -func mulAddVWW(z, x []Word, y, r Word) (c Word) -func addMulVVW(z, x []Word, y Word) (c Word) -func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) diff --git a/libgo/go/big/arith_test.go b/libgo/go/big/arith_test.go deleted file mode 100644 index b6c56c3..0000000 --- a/libgo/go/big/arith_test.go +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package big - -import "testing" - -type funWW func(x, y, c Word) (z1, z0 Word) -type argWW struct { - x, y, c, z1, z0 Word -} - -var sumWW = []argWW{ - {0, 0, 0, 0, 0}, - {0, 1, 0, 0, 1}, - {0, 0, 1, 0, 1}, - {0, 1, 1, 0, 2}, - {12345, 67890, 0, 0, 80235}, - {12345, 67890, 1, 0, 80236}, - {_M, 1, 0, 1, 0}, - {_M, 0, 1, 1, 0}, - {_M, 1, 1, 1, 1}, - {_M, _M, 0, 1, _M - 1}, - {_M, _M, 1, 1, _M}, -} - -func testFunWW(t *testing.T, msg string, f funWW, a argWW) { - z1, z0 := f(a.x, a.y, a.c) - if z1 != a.z1 || z0 != a.z0 { - t.Errorf("%s%+v\n\tgot z1:z0 = %#x:%#x; want %#x:%#x", msg, a, z1, z0, a.z1, a.z0) - } -} - -func TestFunWW(t *testing.T) { - for _, a := range sumWW { - arg := a - testFunWW(t, "addWW_g", addWW_g, arg) - - arg = argWW{a.y, a.x, a.c, a.z1, a.z0} - testFunWW(t, "addWW_g symmetric", addWW_g, arg) - - arg = argWW{a.z0, a.x, a.c, a.z1, a.y} - testFunWW(t, "subWW_g", subWW_g, arg) - - arg = argWW{a.z0, a.y, a.c, a.z1, a.x} - testFunWW(t, "subWW_g symmetric", subWW_g, arg) - } -} - -type funVV func(z, x, y []Word) (c Word) -type argVV struct { - z, x, y nat - c Word -} - -var sumVV = []argVV{ - {}, - {nat{0}, nat{0}, nat{0}, 0}, - {nat{1}, nat{1}, nat{0}, 0}, - {nat{0}, nat{_M}, nat{1}, 1}, - {nat{80235}, nat{12345}, nat{67890}, 0}, - {nat{_M - 1}, nat{_M}, nat{_M}, 1}, - {nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, nat{1, 0, 0, 0}, 1}, - {nat{0, 0, 0, _M}, nat{_M, _M, _M, _M - 1}, nat{1, 0, 0, 0}, 0}, - {nat{0, 0, 0, 0}, nat{_M, 0, _M, 0}, nat{1, _M, 0, _M}, 1}, -} - -func testFunVV(t *testing.T, msg string, f funVV, a argVV) { - z := make(nat, len(a.z)) - c := f(z, a.x, a.y) - for i, zi := range z { - if zi != a.z[i] { - t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i]) - break - } - } - if c != a.c { - t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c) - } -} - -func TestFunVV(t *testing.T) { - for _, a := range sumVV { - arg := a - testFunVV(t, "addVV_g", addVV_g, arg) - testFunVV(t, "addVV", addVV, arg) - - arg = argVV{a.z, a.y, a.x, a.c} - testFunVV(t, "addVV_g symmetric", addVV_g, arg) - testFunVV(t, "addVV symmetric", addVV, arg) - - arg = argVV{a.x, a.z, a.y, a.c} - testFunVV(t, "subVV_g", subVV_g, arg) - testFunVV(t, "subVV", subVV, arg) - - arg = argVV{a.y, a.z, a.x, a.c} - testFunVV(t, "subVV_g symmetric", subVV_g, arg) - testFunVV(t, "subVV symmetric", subVV, arg) - } -} - -type funVW func(z, x []Word, y Word) (c Word) -type argVW struct { - z, x nat - y Word - c Word -} - -var sumVW = []argVW{ - {}, - {nil, nil, 2, 2}, - {nat{0}, nat{0}, 0, 0}, - {nat{1}, nat{0}, 1, 0}, - {nat{1}, nat{1}, 0, 0}, - {nat{0}, nat{_M}, 1, 1}, - {nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, 1, 1}, -} - -var prodVW = []argVW{ - {}, - {nat{0}, nat{0}, 0, 0}, - {nat{0}, nat{_M}, 0, 0}, - {nat{0}, nat{0}, _M, 0}, - {nat{1}, nat{1}, 1, 0}, - {nat{22793}, nat{991}, 23, 0}, - {nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0}, - {nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0}, - {nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0}, - {nat{_M << 1 & _M}, nat{_M}, 1 << 1, _M >> (_W - 1)}, - {nat{_M << 7 & _M}, nat{_M}, 1 << 7, _M >> (_W - 7)}, - {nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, _M >> (_W - 7)}, -} - -var lshVW = []argVW{ - {}, - {nat{0}, nat{0}, 0, 0}, - {nat{0}, nat{0}, 1, 0}, - {nat{0}, nat{0}, 20, 0}, - - {nat{_M}, nat{_M}, 0, 0}, - {nat{_M << 1 & _M}, nat{_M}, 1, 1}, - {nat{_M << 20 & _M}, nat{_M}, 20, _M >> (_W - 20)}, - - {nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0}, - {nat{_M << 1 & _M, _M, _M}, nat{_M, _M, _M}, 1, 1}, - {nat{_M << 20 & _M, _M, _M}, nat{_M, _M, _M}, 20, _M >> (_W - 20)}, -} - -var rshVW = []argVW{ - {}, - {nat{0}, nat{0}, 0, 0}, - {nat{0}, nat{0}, 1, 0}, - {nat{0}, nat{0}, 20, 0}, - - {nat{_M}, nat{_M}, 0, 0}, - {nat{_M >> 1}, nat{_M}, 1, _M << (_W - 1) & _M}, - {nat{_M >> 20}, nat{_M}, 20, _M << (_W - 20) & _M}, - - {nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0}, - {nat{_M, _M, _M >> 1}, nat{_M, _M, _M}, 1, _M << (_W - 1) & _M}, - {nat{_M, _M, _M >> 20}, nat{_M, _M, _M}, 20, _M << (_W - 20) & _M}, -} - -func testFunVW(t *testing.T, msg string, f funVW, a argVW) { - z := make(nat, len(a.z)) - c := f(z, a.x, a.y) - for i, zi := range z { - if zi != a.z[i] { - t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i]) - break - } - } - if c != a.c { - t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c) - } -} - -func makeFunVW(f func(z, x []Word, s uint) (c Word)) funVW { - return func(z, x []Word, s Word) (c Word) { - return f(z, x, uint(s)) - } -} - -func TestFunVW(t *testing.T) { - for _, a := range sumVW { - arg := a - testFunVW(t, "addVW_g", addVW_g, arg) - testFunVW(t, "addVW", addVW, arg) - - arg = argVW{a.x, a.z, a.y, a.c} - testFunVW(t, "subVW_g", subVW_g, arg) - testFunVW(t, "subVW", subVW, arg) - } - - shlVW_g := makeFunVW(shlVU_g) - shlVW := makeFunVW(shlVU) - for _, a := range lshVW { - arg := a - testFunVW(t, "shlVU_g", shlVW_g, arg) - testFunVW(t, "shlVU", shlVW, arg) - } - - shrVW_g := makeFunVW(shrVU_g) - shrVW := makeFunVW(shrVU) - for _, a := range rshVW { - arg := a - testFunVW(t, "shrVU_g", shrVW_g, arg) - testFunVW(t, "shrVU", shrVW, arg) - } -} - -type funVWW func(z, x []Word, y, r Word) (c Word) -type argVWW struct { - z, x nat - y, r Word - c Word -} - -var prodVWW = []argVWW{ - {}, - {nat{0}, nat{0}, 0, 0, 0}, - {nat{991}, nat{0}, 0, 991, 0}, - {nat{0}, nat{_M}, 0, 0, 0}, - {nat{991}, nat{_M}, 0, 991, 0}, - {nat{0}, nat{0}, _M, 0, 0}, - {nat{991}, nat{0}, _M, 991, 0}, - {nat{1}, nat{1}, 1, 0, 0}, - {nat{992}, nat{1}, 1, 991, 0}, - {nat{22793}, nat{991}, 23, 0, 0}, - {nat{22800}, nat{991}, 23, 7, 0}, - {nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0, 0}, - {nat{7, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 7, 0}, - {nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0, 0}, - {nat{991, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 991, 0}, - {nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0, 0}, - {nat{991, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 991, 0}, - {nat{_M << 1 & _M}, nat{_M}, 1 << 1, 0, _M >> (_W - 1)}, - {nat{_M<<1&_M + 1}, nat{_M}, 1 << 1, 1, _M >> (_W - 1)}, - {nat{_M << 7 & _M}, nat{_M}, 1 << 7, 0, _M >> (_W - 7)}, - {nat{_M<<7&_M + 1<<6}, nat{_M}, 1 << 7, 1 << 6, _M >> (_W - 7)}, - {nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 0, _M >> (_W - 7)}, - {nat{_M<<7&_M + 1<<6, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 1 << 6, _M >> (_W - 7)}, -} - -func testFunVWW(t *testing.T, msg string, f funVWW, a argVWW) { - z := make(nat, len(a.z)) - c := f(z, a.x, a.y, a.r) - for i, zi := range z { - if zi != a.z[i] { - t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i]) - break - } - } - if c != a.c { - t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c) - } -} - -// TODO(gri) mulAddVWW and divWVW are symmetric operations but -// their signature is not symmetric. Try to unify. - -type funWVW func(z []Word, xn Word, x []Word, y Word) (r Word) -type argWVW struct { - z nat - xn Word - x nat - y Word - r Word -} - -func testFunWVW(t *testing.T, msg string, f funWVW, a argWVW) { - z := make(nat, len(a.z)) - r := f(z, a.xn, a.x, a.y) - for i, zi := range z { - if zi != a.z[i] { - t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i]) - break - } - } - if r != a.r { - t.Errorf("%s%+v\n\tgot r = %#x; want %#x", msg, a, r, a.r) - } -} - -func TestFunVWW(t *testing.T) { - for _, a := range prodVWW { - arg := a - testFunVWW(t, "mulAddVWW_g", mulAddVWW_g, arg) - testFunVWW(t, "mulAddVWW", mulAddVWW, arg) - - if a.y != 0 && a.r < a.y { - arg := argWVW{a.x, a.c, a.z, a.y, a.r} - testFunWVW(t, "divWVW_g", divWVW_g, arg) - testFunWVW(t, "divWVW", divWVW, arg) - } - } -} - -var mulWWTests = []struct { - x, y Word - q, r Word -}{ - {_M, _M, _M - 1, 1}, - // 32 bit only: {0xc47dfa8c, 50911, 0x98a4, 0x998587f4}, -} - -func TestMulWW(t *testing.T) { - for i, test := range mulWWTests { - q, r := mulWW_g(test.x, test.y) - if q != test.q || r != test.r { - t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r) - } - } -} - -var mulAddWWWTests = []struct { - x, y, c Word - q, r Word -}{ - // TODO(agl): These will only work on 64-bit platforms. - // {15064310297182388543, 0xe7df04d2d35d5d80, 13537600649892366549, 13644450054494335067, 10832252001440893781}, - // {15064310297182388543, 0xdab2f18048baa68d, 13644450054494335067, 12869334219691522700, 14233854684711418382}, - {_M, _M, 0, _M - 1, 1}, - {_M, _M, _M, _M, 0}, -} - -func TestMulAddWWW(t *testing.T) { - for i, test := range mulAddWWWTests { - q, r := mulAddWWW_g(test.x, test.y, test.c) - if q != test.q || r != test.r { - t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r) - } - } -} diff --git a/libgo/go/big/calibrate_test.go b/libgo/go/big/calibrate_test.go deleted file mode 100644 index 1cd93b1..0000000 --- a/libgo/go/big/calibrate_test.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file prints execution times for the Mul benchmark -// given different Karatsuba thresholds. The result may be -// used to manually fine-tune the threshold constant. The -// results are somewhat fragile; use repeated runs to get -// a clear picture. - -// Usage: gotest -calibrate - -package big - -import ( - "flag" - "fmt" - "testing" - "time" -) - -var calibrate = flag.Bool("calibrate", false, "run calibration test") - -// measure returns the time to run f -func measure(f func()) int64 { - const N = 100 - start := time.Nanoseconds() - for i := N; i > 0; i-- { - f() - } - stop := time.Nanoseconds() - return (stop - start) / N -} - -func computeThresholds() { - fmt.Printf("Multiplication times for varying Karatsuba thresholds\n") - fmt.Printf("(run repeatedly for good results)\n") - - // determine Tk, the work load execution time using basic multiplication - karatsubaThreshold = 1e9 // disable karatsuba - Tb := measure(benchmarkMulLoad) - fmt.Printf("Tb = %dns\n", Tb) - - // thresholds - n := 8 // any lower values for the threshold lead to very slow multiplies - th1 := -1 - th2 := -1 - - var deltaOld int64 - for count := -1; count != 0; count-- { - // determine Tk, the work load execution time using Karatsuba multiplication - karatsubaThreshold = n // enable karatsuba - Tk := measure(benchmarkMulLoad) - - // improvement over Tb - delta := (Tb - Tk) * 100 / Tb - - fmt.Printf("n = %3d Tk = %8dns %4d%%", n, Tk, delta) - - // determine break-even point - if Tk < Tb && th1 < 0 { - th1 = n - fmt.Print(" break-even point") - } - - // determine diminishing return - if 0 < delta && delta < deltaOld && th2 < 0 { - th2 = n - fmt.Print(" diminishing return") - } - deltaOld = delta - - fmt.Println() - - // trigger counter - if th1 >= 0 && th2 >= 0 && count < 0 { - count = 20 // this many extra measurements after we got both thresholds - } - - n++ - } -} - -func TestCalibrate(t *testing.T) { - if *calibrate { - computeThresholds() - } -} diff --git a/libgo/go/big/hilbert_test.go b/libgo/go/big/hilbert_test.go deleted file mode 100644 index 1a84341..0000000 --- a/libgo/go/big/hilbert_test.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// A little test program and benchmark for rational arithmetics. -// Computes a Hilbert matrix, its inverse, multiplies them -// and verifies that the product is the identity matrix. - -package big - -import ( - "fmt" - "testing" -) - -type matrix struct { - n, m int - a []*Rat -} - -func (a *matrix) at(i, j int) *Rat { - if !(0 <= i && i < a.n && 0 <= j && j < a.m) { - panic("index out of range") - } - return a.a[i*a.m+j] -} - -func (a *matrix) set(i, j int, x *Rat) { - if !(0 <= i && i < a.n && 0 <= j && j < a.m) { - panic("index out of range") - } - a.a[i*a.m+j] = x -} - -func newMatrix(n, m int) *matrix { - if !(0 <= n && 0 <= m) { - panic("illegal matrix") - } - a := new(matrix) - a.n = n - a.m = m - a.a = make([]*Rat, n*m) - return a -} - -func newUnit(n int) *matrix { - a := newMatrix(n, n) - for i := 0; i < n; i++ { - for j := 0; j < n; j++ { - x := NewRat(0, 1) - if i == j { - x.SetInt64(1) - } - a.set(i, j, x) - } - } - return a -} - -func newHilbert(n int) *matrix { - a := newMatrix(n, n) - for i := 0; i < n; i++ { - for j := 0; j < n; j++ { - a.set(i, j, NewRat(1, int64(i+j+1))) - } - } - return a -} - -func newInverseHilbert(n int) *matrix { - a := newMatrix(n, n) - for i := 0; i < n; i++ { - for j := 0; j < n; j++ { - x1 := new(Rat).SetInt64(int64(i + j + 1)) - x2 := new(Rat).SetInt(new(Int).Binomial(int64(n+i), int64(n-j-1))) - x3 := new(Rat).SetInt(new(Int).Binomial(int64(n+j), int64(n-i-1))) - x4 := new(Rat).SetInt(new(Int).Binomial(int64(i+j), int64(i))) - - x1.Mul(x1, x2) - x1.Mul(x1, x3) - x1.Mul(x1, x4) - x1.Mul(x1, x4) - - if (i+j)&1 != 0 { - x1.Neg(x1) - } - - a.set(i, j, x1) - } - } - return a -} - -func (a *matrix) mul(b *matrix) *matrix { - if a.m != b.n { - panic("illegal matrix multiply") - } - c := newMatrix(a.n, b.m) - for i := 0; i < c.n; i++ { - for j := 0; j < c.m; j++ { - x := NewRat(0, 1) - for k := 0; k < a.m; k++ { - x.Add(x, new(Rat).Mul(a.at(i, k), b.at(k, j))) - } - c.set(i, j, x) - } - } - return c -} - -func (a *matrix) eql(b *matrix) bool { - if a.n != b.n || a.m != b.m { - return false - } - for i := 0; i < a.n; i++ { - for j := 0; j < a.m; j++ { - if a.at(i, j).Cmp(b.at(i, j)) != 0 { - return false - } - } - } - return true -} - -func (a *matrix) String() string { - s := "" - for i := 0; i < a.n; i++ { - for j := 0; j < a.m; j++ { - s += fmt.Sprintf("\t%s", a.at(i, j)) - } - s += "\n" - } - return s -} - -func doHilbert(t *testing.T, n int) { - a := newHilbert(n) - b := newInverseHilbert(n) - I := newUnit(n) - ab := a.mul(b) - if !ab.eql(I) { - if t == nil { - panic("Hilbert failed") - } - t.Errorf("a = %s\n", a) - t.Errorf("b = %s\n", b) - t.Errorf("a*b = %s\n", ab) - t.Errorf("I = %s\n", I) - } -} - -func TestHilbert(t *testing.T) { - doHilbert(t, 10) -} - -func BenchmarkHilbert(b *testing.B) { - for i := 0; i < b.N; i++ { - doHilbert(nil, 10) - } -} diff --git a/libgo/go/big/int.go b/libgo/go/big/int.go deleted file mode 100644 index c6affbb..0000000 --- a/libgo/go/big/int.go +++ /dev/null @@ -1,873 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file implements signed multi-precision integers. - -package big - -import ( - "errors" - "fmt" - "io" - "rand" - "strings" -) - -// An Int represents a signed multi-precision integer. -// The zero value for an Int represents the value 0. -type Int struct { - neg bool // sign - abs nat // absolute value of the integer -} - -var intOne = &Int{false, natOne} - -// Sign returns: -// -// -1 if x < 0 -// 0 if x == 0 -// +1 if x > 0 -// -func (x *Int) Sign() int { - if len(x.abs) == 0 { - return 0 - } - if x.neg { - return -1 - } - return 1 -} - -// SetInt64 sets z to x and returns z. -func (z *Int) SetInt64(x int64) *Int { - neg := false - if x < 0 { - neg = true - x = -x - } - z.abs = z.abs.setUint64(uint64(x)) - z.neg = neg - return z -} - -// NewInt allocates and returns a new Int set to x. -func NewInt(x int64) *Int { - return new(Int).SetInt64(x) -} - -// Set sets z to x and returns z. -func (z *Int) Set(x *Int) *Int { - if z != x { - z.abs = z.abs.set(x.abs) - z.neg = x.neg - } - return z -} - -// Abs sets z to |x| (the absolute value of x) and returns z. -func (z *Int) Abs(x *Int) *Int { - z.Set(x) - z.neg = false - return z -} - -// Neg sets z to -x and returns z. -func (z *Int) Neg(x *Int) *Int { - z.Set(x) - z.neg = len(z.abs) > 0 && !z.neg // 0 has no sign - return z -} - -// Add sets z to the sum x+y and returns z. -func (z *Int) Add(x, y *Int) *Int { - neg := x.neg - if x.neg == y.neg { - // x + y == x + y - // (-x) + (-y) == -(x + y) - z.abs = z.abs.add(x.abs, y.abs) - } else { - // x + (-y) == x - y == -(y - x) - // (-x) + y == y - x == -(x - y) - if x.abs.cmp(y.abs) >= 0 { - z.abs = z.abs.sub(x.abs, y.abs) - } else { - neg = !neg - z.abs = z.abs.sub(y.abs, x.abs) - } - } - z.neg = len(z.abs) > 0 && neg // 0 has no sign - return z -} - -// Sub sets z to the difference x-y and returns z. -func (z *Int) Sub(x, y *Int) *Int { - neg := x.neg - if x.neg != y.neg { - // x - (-y) == x + y - // (-x) - y == -(x + y) - z.abs = z.abs.add(x.abs, y.abs) - } else { - // x - y == x - y == -(y - x) - // (-x) - (-y) == y - x == -(x - y) - if x.abs.cmp(y.abs) >= 0 { - z.abs = z.abs.sub(x.abs, y.abs) - } else { - neg = !neg - z.abs = z.abs.sub(y.abs, x.abs) - } - } - z.neg = len(z.abs) > 0 && neg // 0 has no sign - return z -} - -// Mul sets z to the product x*y and returns z. -func (z *Int) Mul(x, y *Int) *Int { - // x * y == x * y - // x * (-y) == -(x * y) - // (-x) * y == -(x * y) - // (-x) * (-y) == x * y - z.abs = z.abs.mul(x.abs, y.abs) - z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign - return z -} - -// MulRange sets z to the product of all integers -// in the range [a, b] inclusively and returns z. -// If a > b (empty range), the result is 1. -func (z *Int) MulRange(a, b int64) *Int { - switch { - case a > b: - return z.SetInt64(1) // empty range - case a <= 0 && b >= 0: - return z.SetInt64(0) // range includes 0 - } - // a <= b && (b < 0 || a > 0) - - neg := false - if a < 0 { - neg = (b-a)&1 == 0 - a, b = -b, -a - } - - z.abs = z.abs.mulRange(uint64(a), uint64(b)) - z.neg = neg - return z -} - -// Binomial sets z to the binomial coefficient of (n, k) and returns z. -func (z *Int) Binomial(n, k int64) *Int { - var a, b Int - a.MulRange(n-k+1, n) - b.MulRange(1, k) - return z.Quo(&a, &b) -} - -// Quo sets z to the quotient x/y for y != 0 and returns z. -// If y == 0, a division-by-zero run-time panic occurs. -// Quo implements truncated division (like Go); see QuoRem for more details. -func (z *Int) Quo(x, y *Int) *Int { - z.abs, _ = z.abs.div(nil, x.abs, y.abs) - z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign - return z -} - -// Rem sets z to the remainder x%y for y != 0 and returns z. -// If y == 0, a division-by-zero run-time panic occurs. -// Rem implements truncated modulus (like Go); see QuoRem for more details. -func (z *Int) Rem(x, y *Int) *Int { - _, z.abs = nat{}.div(z.abs, x.abs, y.abs) - z.neg = len(z.abs) > 0 && x.neg // 0 has no sign - return z -} - -// QuoRem sets z to the quotient x/y and r to the remainder x%y -// and returns the pair (z, r) for y != 0. -// If y == 0, a division-by-zero run-time panic occurs. -// -// QuoRem implements T-division and modulus (like Go): -// -// q = x/y with the result truncated to zero -// r = x - y*q -// -// (See Daan Leijen, ``Division and Modulus for Computer Scientists''.) -// -func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) { - z.abs, r.abs = z.abs.div(r.abs, x.abs, y.abs) - z.neg, r.neg = len(z.abs) > 0 && x.neg != y.neg, len(r.abs) > 0 && x.neg // 0 has no sign - return z, r -} - -// Div sets z to the quotient x/y for y != 0 and returns z. -// If y == 0, a division-by-zero run-time panic occurs. -// Div implements Euclidean division (unlike Go); see DivMod for more details. -func (z *Int) Div(x, y *Int) *Int { - y_neg := y.neg // z may be an alias for y - var r Int - z.QuoRem(x, y, &r) - if r.neg { - if y_neg { - z.Add(z, intOne) - } else { - z.Sub(z, intOne) - } - } - return z -} - -// Mod sets z to the modulus x%y for y != 0 and returns z. -// If y == 0, a division-by-zero run-time panic occurs. -// Mod implements Euclidean modulus (unlike Go); see DivMod for more details. -func (z *Int) Mod(x, y *Int) *Int { - y0 := y // save y - if z == y || alias(z.abs, y.abs) { - y0 = new(Int).Set(y) - } - var q Int - q.QuoRem(x, y, z) - if z.neg { - if y0.neg { - z.Sub(z, y0) - } else { - z.Add(z, y0) - } - } - return z -} - -// DivMod sets z to the quotient x div y and m to the modulus x mod y -// and returns the pair (z, m) for y != 0. -// If y == 0, a division-by-zero run-time panic occurs. -// -// DivMod implements Euclidean division and modulus (unlike Go): -// -// q = x div y such that -// m = x - y*q with 0 <= m < |q| -// -// (See Raymond T. Boute, ``The Euclidean definition of the functions -// div and mod''. ACM Transactions on Programming Languages and -// Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992. -// ACM press.) -// -func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) { - y0 := y // save y - if z == y || alias(z.abs, y.abs) { - y0 = new(Int).Set(y) - } - z.QuoRem(x, y, m) - if m.neg { - if y0.neg { - z.Add(z, intOne) - m.Sub(m, y0) - } else { - z.Sub(z, intOne) - m.Add(m, y0) - } - } - return z, m -} - -// Cmp compares x and y and returns: -// -// -1 if x < y -// 0 if x == y -// +1 if x > y -// -func (x *Int) Cmp(y *Int) (r int) { - // x cmp y == x cmp y - // x cmp (-y) == x - // (-x) cmp y == y - // (-x) cmp (-y) == -(x cmp y) - switch { - case x.neg == y.neg: - r = x.abs.cmp(y.abs) - if x.neg { - r = -r - } - case x.neg: - r = -1 - default: - r = 1 - } - return -} - -func (x *Int) String() string { - switch { - case x == nil: - return "" - case x.neg: - return "-" + x.abs.decimalString() - } - return x.abs.decimalString() -} - -func charset(ch rune) string { - switch ch { - case 'b': - return lowercaseDigits[0:2] - case 'o': - return lowercaseDigits[0:8] - case 'd', 's', 'v': - return lowercaseDigits[0:10] - case 'x': - return lowercaseDigits[0:16] - case 'X': - return uppercaseDigits[0:16] - } - return "" // unknown format -} - -// write count copies of text to s -func writeMultiple(s fmt.State, text string, count int) { - if len(text) > 0 { - b := []byte(text) - for ; count > 0; count-- { - s.Write(b) - } - } -} - -// Format is a support routine for fmt.Formatter. It accepts -// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x' -// (lowercase hexadecimal), and 'X' (uppercase hexadecimal). -// Also supported are the full suite of package fmt's format -// verbs for integral types, including '+', '-', and ' ' -// for sign control, '#' for leading zero in octal and for -// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X" -// respectively, specification of minimum digits precision, -// output field width, space or zero padding, and left or -// right justification. -// -func (x *Int) Format(s fmt.State, ch rune) { - cs := charset(ch) - - // special cases - switch { - case cs == "": - // unknown format - fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String()) - return - case x == nil: - fmt.Fprint(s, "") - return - } - - // determine sign character - sign := "" - switch { - case x.neg: - sign = "-" - case s.Flag('+'): // supersedes ' ' when both specified - sign = "+" - case s.Flag(' '): - sign = " " - } - - // determine prefix characters for indicating output base - prefix := "" - if s.Flag('#') { - switch ch { - case 'o': // octal - prefix = "0" - case 'x': // hexadecimal - prefix = "0x" - case 'X': - prefix = "0X" - } - } - - // determine digits with base set by len(cs) and digit characters from cs - digits := x.abs.string(cs) - - // number of characters for the three classes of number padding - var left int // space characters to left of digits for right justification ("%8d") - var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d") - var right int // space characters to right of digits for left justification ("%-8d") - - // determine number padding from precision: the least number of digits to output - precision, precisionSet := s.Precision() - if precisionSet { - switch { - case len(digits) < precision: - zeroes = precision - len(digits) // count of zero padding - case digits == "0" && precision == 0: - return // print nothing if zero value (x == 0) and zero precision ("." or ".0") - } - } - - // determine field pad from width: the least number of characters to output - length := len(sign) + len(prefix) + zeroes + len(digits) - if width, widthSet := s.Width(); widthSet && length < width { // pad as specified - switch d := width - length; { - case s.Flag('-'): - // pad on the right with spaces; supersedes '0' when both specified - right = d - case s.Flag('0') && !precisionSet: - // pad with zeroes unless precision also specified - zeroes = d - default: - // pad on the left with spaces - left = d - } - } - - // print number as [left pad][sign][prefix][zero pad][digits][right pad] - writeMultiple(s, " ", left) - writeMultiple(s, sign, 1) - writeMultiple(s, prefix, 1) - writeMultiple(s, "0", zeroes) - writeMultiple(s, digits, 1) - writeMultiple(s, " ", right) -} - -// scan sets z to the integer value corresponding to the longest possible prefix -// read from r representing a signed integer number in a given conversion base. -// It returns z, the actual conversion base used, and an error, if any. In the -// error case, the value of z is undefined but the returned value is nil. The -// syntax follows the syntax of integer literals in Go. -// -// The base argument must be 0 or a value from 2 through MaxBase. If the base -// is 0, the string prefix determines the actual conversion base. A prefix of -// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a -// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10. -// -func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, error) { - // determine sign - ch, _, err := r.ReadRune() - if err != nil { - return nil, 0, err - } - neg := false - switch ch { - case '-': - neg = true - case '+': // nothing to do - default: - r.UnreadRune() - } - - // determine mantissa - z.abs, base, err = z.abs.scan(r, base) - if err != nil { - return nil, base, err - } - z.neg = len(z.abs) > 0 && neg // 0 has no sign - - return z, base, nil -} - -// Scan is a support routine for fmt.Scanner; it sets z to the value of -// the scanned number. It accepts the formats 'b' (binary), 'o' (octal), -// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal). -func (z *Int) Scan(s fmt.ScanState, ch rune) error { - s.SkipSpace() // skip leading space characters - base := 0 - switch ch { - case 'b': - base = 2 - case 'o': - base = 8 - case 'd': - base = 10 - case 'x', 'X': - base = 16 - case 's', 'v': - // let scan determine the base - default: - return errors.New("Int.Scan: invalid verb") - } - _, _, err := z.scan(s, base) - return err -} - -// Int64 returns the int64 representation of x. -// If x cannot be represented in an int64, the result is undefined. -func (x *Int) Int64() int64 { - if len(x.abs) == 0 { - return 0 - } - v := int64(x.abs[0]) - if _W == 32 && len(x.abs) > 1 { - v |= int64(x.abs[1]) << 32 - } - if x.neg { - v = -v - } - return v -} - -// SetString sets z to the value of s, interpreted in the given base, -// and returns z and a boolean indicating success. If SetString fails, -// the value of z is undefined but the returned value is nil. -// -// The base argument must be 0 or a value from 2 through MaxBase. If the base -// is 0, the string prefix determines the actual conversion base. A prefix of -// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a -// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10. -// -func (z *Int) SetString(s string, base int) (*Int, bool) { - r := strings.NewReader(s) - _, _, err := z.scan(r, base) - if err != nil { - return nil, false - } - _, _, err = r.ReadRune() - if err != io.EOF { - return nil, false - } - return z, true // err == os.EOF => scan consumed all of s -} - -// SetBytes interprets buf as the bytes of a big-endian unsigned -// integer, sets z to that value, and returns z. -func (z *Int) SetBytes(buf []byte) *Int { - z.abs = z.abs.setBytes(buf) - z.neg = false - return z -} - -// Bytes returns the absolute value of z as a big-endian byte slice. -func (z *Int) Bytes() []byte { - buf := make([]byte, len(z.abs)*_S) - return buf[z.abs.bytes(buf):] -} - -// BitLen returns the length of the absolute value of z in bits. -// The bit length of 0 is 0. -func (z *Int) BitLen() int { - return z.abs.bitLen() -} - -// Exp sets z = x**y mod m. If m is nil, z = x**y. -// See Knuth, volume 2, section 4.6.3. -func (z *Int) Exp(x, y, m *Int) *Int { - if y.neg || len(y.abs) == 0 { - neg := x.neg - z.SetInt64(1) - z.neg = neg - return z - } - - var mWords nat - if m != nil { - mWords = m.abs - } - - z.abs = z.abs.expNN(x.abs, y.abs, mWords) - z.neg = len(z.abs) > 0 && x.neg && y.abs[0]&1 == 1 // 0 has no sign - return z -} - -// GcdInt sets d to the greatest common divisor of a and b, which must be -// positive numbers. -// If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y. -// If either a or b is not positive, GcdInt sets d = x = y = 0. -func GcdInt(d, x, y, a, b *Int) { - if a.neg || b.neg { - d.SetInt64(0) - if x != nil { - x.SetInt64(0) - } - if y != nil { - y.SetInt64(0) - } - return - } - - A := new(Int).Set(a) - B := new(Int).Set(b) - - X := new(Int) - Y := new(Int).SetInt64(1) - - lastX := new(Int).SetInt64(1) - lastY := new(Int) - - q := new(Int) - temp := new(Int) - - for len(B.abs) > 0 { - r := new(Int) - q, r = q.QuoRem(A, B, r) - - A, B = B, r - - temp.Set(X) - X.Mul(X, q) - X.neg = !X.neg - X.Add(X, lastX) - lastX.Set(temp) - - temp.Set(Y) - Y.Mul(Y, q) - Y.neg = !Y.neg - Y.Add(Y, lastY) - lastY.Set(temp) - } - - if x != nil { - *x = *lastX - } - - if y != nil { - *y = *lastY - } - - *d = *A -} - -// ProbablyPrime performs n Miller-Rabin tests to check whether z is prime. -// If it returns true, z is prime with probability 1 - 1/4^n. -// If it returns false, z is not prime. -func ProbablyPrime(z *Int, n int) bool { - return !z.neg && z.abs.probablyPrime(n) -} - -// Rand sets z to a pseudo-random number in [0, n) and returns z. -func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int { - z.neg = false - if n.neg == true || len(n.abs) == 0 { - z.abs = nil - return z - } - z.abs = z.abs.random(rnd, n.abs, n.abs.bitLen()) - return z -} - -// ModInverse sets z to the multiplicative inverse of g in the group ℤ/pℤ (where -// p is a prime) and returns z. -func (z *Int) ModInverse(g, p *Int) *Int { - var d Int - GcdInt(&d, z, nil, g, p) - // x and y are such that g*x + p*y = d. Since p is prime, d = 1. Taking - // that modulo p results in g*x = 1, therefore x is the inverse element. - if z.neg { - z.Add(z, p) - } - return z -} - -// Lsh sets z = x << n and returns z. -func (z *Int) Lsh(x *Int, n uint) *Int { - z.abs = z.abs.shl(x.abs, n) - z.neg = x.neg - return z -} - -// Rsh sets z = x >> n and returns z. -func (z *Int) Rsh(x *Int, n uint) *Int { - if x.neg { - // (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1) - t := z.abs.sub(x.abs, natOne) // no underflow because |x| > 0 - t = t.shr(t, n) - z.abs = t.add(t, natOne) - z.neg = true // z cannot be zero if x is negative - return z - } - - z.abs = z.abs.shr(x.abs, n) - z.neg = false - return z -} - -// Bit returns the value of the i'th bit of z. That is, it -// returns (z>>i)&1. The bit index i must be >= 0. -func (z *Int) Bit(i int) uint { - if i < 0 { - panic("negative bit index") - } - if z.neg { - t := nat{}.sub(z.abs, natOne) - return t.bit(uint(i)) ^ 1 - } - - return z.abs.bit(uint(i)) -} - -// SetBit sets the i'th bit of z to bit and returns z. -// That is, if bit is 1 SetBit sets z = x | (1 << i); -// if bit is 0 it sets z = x &^ (1 << i). If bit is not 0 or 1, -// SetBit will panic. -func (z *Int) SetBit(x *Int, i int, b uint) *Int { - if i < 0 { - panic("negative bit index") - } - if x.neg { - t := z.abs.sub(x.abs, natOne) - t = t.setBit(t, uint(i), b^1) - z.abs = t.add(t, natOne) - z.neg = len(z.abs) > 0 - return z - } - z.abs = z.abs.setBit(x.abs, uint(i), b) - z.neg = false - return z -} - -// And sets z = x & y and returns z. -func (z *Int) And(x, y *Int) *Int { - if x.neg == y.neg { - if x.neg { - // (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1) - x1 := nat{}.sub(x.abs, natOne) - y1 := nat{}.sub(y.abs, natOne) - z.abs = z.abs.add(z.abs.or(x1, y1), natOne) - z.neg = true // z cannot be zero if x and y are negative - return z - } - - // x & y == x & y - z.abs = z.abs.and(x.abs, y.abs) - z.neg = false - return z - } - - // x.neg != y.neg - if x.neg { - x, y = y, x // & is symmetric - } - - // x & (-y) == x & ^(y-1) == x &^ (y-1) - y1 := nat{}.sub(y.abs, natOne) - z.abs = z.abs.andNot(x.abs, y1) - z.neg = false - return z -} - -// AndNot sets z = x &^ y and returns z. -func (z *Int) AndNot(x, y *Int) *Int { - if x.neg == y.neg { - if x.neg { - // (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1) - x1 := nat{}.sub(x.abs, natOne) - y1 := nat{}.sub(y.abs, natOne) - z.abs = z.abs.andNot(y1, x1) - z.neg = false - return z - } - - // x &^ y == x &^ y - z.abs = z.abs.andNot(x.abs, y.abs) - z.neg = false - return z - } - - if x.neg { - // (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1) - x1 := nat{}.sub(x.abs, natOne) - z.abs = z.abs.add(z.abs.or(x1, y.abs), natOne) - z.neg = true // z cannot be zero if x is negative and y is positive - return z - } - - // x &^ (-y) == x &^ ^(y-1) == x & (y-1) - y1 := nat{}.add(y.abs, natOne) - z.abs = z.abs.and(x.abs, y1) - z.neg = false - return z -} - -// Or sets z = x | y and returns z. -func (z *Int) Or(x, y *Int) *Int { - if x.neg == y.neg { - if x.neg { - // (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1) - x1 := nat{}.sub(x.abs, natOne) - y1 := nat{}.sub(y.abs, natOne) - z.abs = z.abs.add(z.abs.and(x1, y1), natOne) - z.neg = true // z cannot be zero if x and y are negative - return z - } - - // x | y == x | y - z.abs = z.abs.or(x.abs, y.abs) - z.neg = false - return z - } - - // x.neg != y.neg - if x.neg { - x, y = y, x // | is symmetric - } - - // x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1) - y1 := nat{}.sub(y.abs, natOne) - z.abs = z.abs.add(z.abs.andNot(y1, x.abs), natOne) - z.neg = true // z cannot be zero if one of x or y is negative - return z -} - -// Xor sets z = x ^ y and returns z. -func (z *Int) Xor(x, y *Int) *Int { - if x.neg == y.neg { - if x.neg { - // (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1) - x1 := nat{}.sub(x.abs, natOne) - y1 := nat{}.sub(y.abs, natOne) - z.abs = z.abs.xor(x1, y1) - z.neg = false - return z - } - - // x ^ y == x ^ y - z.abs = z.abs.xor(x.abs, y.abs) - z.neg = false - return z - } - - // x.neg != y.neg - if x.neg { - x, y = y, x // ^ is symmetric - } - - // x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1) - y1 := nat{}.sub(y.abs, natOne) - z.abs = z.abs.add(z.abs.xor(x.abs, y1), natOne) - z.neg = true // z cannot be zero if only one of x or y is negative - return z -} - -// Not sets z = ^x and returns z. -func (z *Int) Not(x *Int) *Int { - if x.neg { - // ^(-x) == ^(^(x-1)) == x-1 - z.abs = z.abs.sub(x.abs, natOne) - z.neg = false - return z - } - - // ^x == -x-1 == -(x+1) - z.abs = z.abs.add(x.abs, natOne) - z.neg = true // z cannot be zero if x is positive - return z -} - -// Gob codec version. Permits backward-compatible changes to the encoding. -const intGobVersion byte = 1 - -// GobEncode implements the gob.GobEncoder interface. -func (z *Int) GobEncode() ([]byte, error) { - buf := make([]byte, 1+len(z.abs)*_S) // extra byte for version and sign bit - i := z.abs.bytes(buf) - 1 // i >= 0 - b := intGobVersion << 1 // make space for sign bit - if z.neg { - b |= 1 - } - buf[i] = b - return buf[i:], nil -} - -// GobDecode implements the gob.GobDecoder interface. -func (z *Int) GobDecode(buf []byte) error { - if len(buf) == 0 { - return errors.New("Int.GobDecode: no data") - } - b := buf[0] - if b>>1 != intGobVersion { - return errors.New(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1)) - } - z.neg = b&1 != 0 - z.abs = z.abs.setBytes(buf[1:]) - return nil -} diff --git a/libgo/go/big/int_test.go b/libgo/go/big/int_test.go deleted file mode 100644 index d66bb5f..0000000 --- a/libgo/go/big/int_test.go +++ /dev/null @@ -1,1403 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package big - -import ( - "bytes" - "encoding/hex" - "fmt" - "gob" - "testing" - "testing/quick" -) - -func isNormalized(x *Int) bool { - if len(x.abs) == 0 { - return !x.neg - } - // len(x.abs) > 0 - return x.abs[len(x.abs)-1] != 0 -} - -type funZZ func(z, x, y *Int) *Int -type argZZ struct { - z, x, y *Int -} - -var sumZZ = []argZZ{ - {NewInt(0), NewInt(0), NewInt(0)}, - {NewInt(1), NewInt(1), NewInt(0)}, - {NewInt(1111111110), NewInt(123456789), NewInt(987654321)}, - {NewInt(-1), NewInt(-1), NewInt(0)}, - {NewInt(864197532), NewInt(-123456789), NewInt(987654321)}, - {NewInt(-1111111110), NewInt(-123456789), NewInt(-987654321)}, -} - -var prodZZ = []argZZ{ - {NewInt(0), NewInt(0), NewInt(0)}, - {NewInt(0), NewInt(1), NewInt(0)}, - {NewInt(1), NewInt(1), NewInt(1)}, - {NewInt(-991 * 991), NewInt(991), NewInt(-991)}, - // TODO(gri) add larger products -} - -func TestSignZ(t *testing.T) { - var zero Int - for _, a := range sumZZ { - s := a.z.Sign() - e := a.z.Cmp(&zero) - if s != e { - t.Errorf("got %d; want %d for z = %v", s, e, a.z) - } - } -} - -func TestSetZ(t *testing.T) { - for _, a := range sumZZ { - var z Int - z.Set(a.z) - if !isNormalized(&z) { - t.Errorf("%v is not normalized", z) - } - if (&z).Cmp(a.z) != 0 { - t.Errorf("got z = %v; want %v", z, a.z) - } - } -} - -func TestAbsZ(t *testing.T) { - var zero Int - for _, a := range sumZZ { - var z Int - z.Abs(a.z) - var e Int - e.Set(a.z) - if e.Cmp(&zero) < 0 { - e.Sub(&zero, &e) - } - if z.Cmp(&e) != 0 { - t.Errorf("got z = %v; want %v", z, e) - } - } -} - -func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) { - var z Int - f(&z, a.x, a.y) - if !isNormalized(&z) { - t.Errorf("%s%v is not normalized", z, msg) - } - if (&z).Cmp(a.z) != 0 { - t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z) - } -} - -func TestSumZZ(t *testing.T) { - AddZZ := func(z, x, y *Int) *Int { return z.Add(x, y) } - SubZZ := func(z, x, y *Int) *Int { return z.Sub(x, y) } - for _, a := range sumZZ { - arg := a - testFunZZ(t, "AddZZ", AddZZ, arg) - - arg = argZZ{a.z, a.y, a.x} - testFunZZ(t, "AddZZ symmetric", AddZZ, arg) - - arg = argZZ{a.x, a.z, a.y} - testFunZZ(t, "SubZZ", SubZZ, arg) - - arg = argZZ{a.y, a.z, a.x} - testFunZZ(t, "SubZZ symmetric", SubZZ, arg) - } -} - -func TestProdZZ(t *testing.T) { - MulZZ := func(z, x, y *Int) *Int { return z.Mul(x, y) } - for _, a := range prodZZ { - arg := a - testFunZZ(t, "MulZZ", MulZZ, arg) - - arg = argZZ{a.z, a.y, a.x} - testFunZZ(t, "MulZZ symmetric", MulZZ, arg) - } -} - -// mulBytes returns x*y via grade school multiplication. Both inputs -// and the result are assumed to be in big-endian representation (to -// match the semantics of Int.Bytes and Int.SetBytes). -func mulBytes(x, y []byte) []byte { - z := make([]byte, len(x)+len(y)) - - // multiply - k0 := len(z) - 1 - for j := len(y) - 1; j >= 0; j-- { - d := int(y[j]) - if d != 0 { - k := k0 - carry := 0 - for i := len(x) - 1; i >= 0; i-- { - t := int(z[k]) + int(x[i])*d + carry - z[k], carry = byte(t), t>>8 - k-- - } - z[k] = byte(carry) - } - k0-- - } - - // normalize (remove leading 0's) - i := 0 - for i < len(z) && z[i] == 0 { - i++ - } - - return z[i:] -} - -func checkMul(a, b []byte) bool { - var x, y, z1 Int - x.SetBytes(a) - y.SetBytes(b) - z1.Mul(&x, &y) - - var z2 Int - z2.SetBytes(mulBytes(a, b)) - - return z1.Cmp(&z2) == 0 -} - -func TestMul(t *testing.T) { - if err := quick.Check(checkMul, nil); err != nil { - t.Error(err) - } -} - -var mulRangesZ = []struct { - a, b int64 - prod string -}{ - // entirely positive ranges are covered by mulRangesN - {-1, 1, "0"}, - {-2, -1, "2"}, - {-3, -2, "6"}, - {-3, -1, "-6"}, - {1, 3, "6"}, - {-10, -10, "-10"}, - {0, -1, "1"}, // empty range - {-1, -100, "1"}, // empty range - {-1, 1, "0"}, // range includes 0 - {-1e9, 0, "0"}, // range includes 0 - {-1e9, 1e9, "0"}, // range includes 0 - {-10, -1, "3628800"}, // 10! - {-20, -2, "-2432902008176640000"}, // -20! - {-99, -1, - "-933262154439441526816992388562667004907159682643816214685929" + - "638952175999932299156089414639761565182862536979208272237582" + - "511852109168640000000000000000000000", // -99! - }, -} - -func TestMulRangeZ(t *testing.T) { - var tmp Int - // test entirely positive ranges - for i, r := range mulRangesN { - prod := tmp.MulRange(int64(r.a), int64(r.b)).String() - if prod != r.prod { - t.Errorf("#%da: got %s; want %s", i, prod, r.prod) - } - } - // test other ranges - for i, r := range mulRangesZ { - prod := tmp.MulRange(r.a, r.b).String() - if prod != r.prod { - t.Errorf("#%db: got %s; want %s", i, prod, r.prod) - } - } -} - -var stringTests = []struct { - in string - out string - base int - val int64 - ok bool -}{ - {in: "", ok: false}, - {in: "a", ok: false}, - {in: "z", ok: false}, - {in: "+", ok: false}, - {in: "-", ok: false}, - {in: "0b", ok: false}, - {in: "0x", ok: false}, - {in: "2", base: 2, ok: false}, - {in: "0b2", base: 0, ok: false}, - {in: "08", ok: false}, - {in: "8", base: 8, ok: false}, - {in: "0xg", base: 0, ok: false}, - {in: "g", base: 16, ok: false}, - {"0", "0", 0, 0, true}, - {"0", "0", 10, 0, true}, - {"0", "0", 16, 0, true}, - {"+0", "0", 0, 0, true}, - {"-0", "0", 0, 0, true}, - {"10", "10", 0, 10, true}, - {"10", "10", 10, 10, true}, - {"10", "10", 16, 16, true}, - {"-10", "-10", 16, -16, true}, - {"+10", "10", 16, 16, true}, - {"0x10", "16", 0, 16, true}, - {in: "0x10", base: 16, ok: false}, - {"-0x10", "-16", 0, -16, true}, - {"+0x10", "16", 0, 16, true}, - {"00", "0", 0, 0, true}, - {"0", "0", 8, 0, true}, - {"07", "7", 0, 7, true}, - {"7", "7", 8, 7, true}, - {"023", "19", 0, 19, true}, - {"23", "23", 8, 19, true}, - {"cafebabe", "cafebabe", 16, 0xcafebabe, true}, - {"0b0", "0", 0, 0, true}, - {"-111", "-111", 2, -7, true}, - {"-0b111", "-7", 0, -7, true}, - {"0b1001010111", "599", 0, 0x257, true}, - {"1001010111", "1001010111", 2, 0x257, true}, -} - -func format(base int) string { - switch base { - case 2: - return "%b" - case 8: - return "%o" - case 16: - return "%x" - } - return "%d" -} - -func TestGetString(t *testing.T) { - z := new(Int) - for i, test := range stringTests { - if !test.ok { - continue - } - z.SetInt64(test.val) - - if test.base == 10 { - s := z.String() - if s != test.out { - t.Errorf("#%da got %s; want %s", i, s, test.out) - } - } - - s := fmt.Sprintf(format(test.base), z) - if s != test.out { - t.Errorf("#%db got %s; want %s", i, s, test.out) - } - } -} - -func TestSetString(t *testing.T) { - tmp := new(Int) - for i, test := range stringTests { - // initialize to a non-zero value so that issues with parsing - // 0 are detected - tmp.SetInt64(1234567890) - n1, ok1 := new(Int).SetString(test.in, test.base) - n2, ok2 := tmp.SetString(test.in, test.base) - expected := NewInt(test.val) - if ok1 != test.ok || ok2 != test.ok { - t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok) - continue - } - if !ok1 { - if n1 != nil { - t.Errorf("#%d (input '%s') n1 != nil", i, test.in) - } - continue - } - if !ok2 { - if n2 != nil { - t.Errorf("#%d (input '%s') n2 != nil", i, test.in) - } - continue - } - - if ok1 && !isNormalized(n1) { - t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1) - } - if ok2 && !isNormalized(n2) { - t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2) - } - - if n1.Cmp(expected) != 0 { - t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val) - } - if n2.Cmp(expected) != 0 { - t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val) - } - } -} - -var formatTests = []struct { - input string - format string - output string -}{ - {"", "%x", ""}, - {"", "%#x", ""}, - {"", "%#y", "%!y(big.Int=)"}, - - {"10", "%b", "1010"}, - {"10", "%o", "12"}, - {"10", "%d", "10"}, - {"10", "%v", "10"}, - {"10", "%x", "a"}, - {"10", "%X", "A"}, - {"-10", "%X", "-A"}, - {"10", "%y", "%!y(big.Int=10)"}, - {"-10", "%y", "%!y(big.Int=-10)"}, - - {"10", "%#b", "1010"}, - {"10", "%#o", "012"}, - {"10", "%#d", "10"}, - {"10", "%#v", "10"}, - {"10", "%#x", "0xa"}, - {"10", "%#X", "0XA"}, - {"-10", "%#X", "-0XA"}, - {"10", "%#y", "%!y(big.Int=10)"}, - {"-10", "%#y", "%!y(big.Int=-10)"}, - - {"1234", "%d", "1234"}, - {"1234", "%3d", "1234"}, - {"1234", "%4d", "1234"}, - {"-1234", "%d", "-1234"}, - {"1234", "% 5d", " 1234"}, - {"1234", "%+5d", "+1234"}, - {"1234", "%-5d", "1234 "}, - {"1234", "%x", "4d2"}, - {"1234", "%X", "4D2"}, - {"-1234", "%3x", "-4d2"}, - {"-1234", "%4x", "-4d2"}, - {"-1234", "%5x", " -4d2"}, - {"-1234", "%-5x", "-4d2 "}, - {"1234", "%03d", "1234"}, - {"1234", "%04d", "1234"}, - {"1234", "%05d", "01234"}, - {"1234", "%06d", "001234"}, - {"-1234", "%06d", "-01234"}, - {"1234", "%+06d", "+01234"}, - {"1234", "% 06d", " 01234"}, - {"1234", "%-6d", "1234 "}, - {"1234", "%-06d", "1234 "}, - {"-1234", "%-06d", "-1234 "}, - - {"1234", "%.3d", "1234"}, - {"1234", "%.4d", "1234"}, - {"1234", "%.5d", "01234"}, - {"1234", "%.6d", "001234"}, - {"-1234", "%.3d", "-1234"}, - {"-1234", "%.4d", "-1234"}, - {"-1234", "%.5d", "-01234"}, - {"-1234", "%.6d", "-001234"}, - - {"1234", "%8.3d", " 1234"}, - {"1234", "%8.4d", " 1234"}, - {"1234", "%8.5d", " 01234"}, - {"1234", "%8.6d", " 001234"}, - {"-1234", "%8.3d", " -1234"}, - {"-1234", "%8.4d", " -1234"}, - {"-1234", "%8.5d", " -01234"}, - {"-1234", "%8.6d", " -001234"}, - - {"1234", "%+8.3d", " +1234"}, - {"1234", "%+8.4d", " +1234"}, - {"1234", "%+8.5d", " +01234"}, - {"1234", "%+8.6d", " +001234"}, - {"-1234", "%+8.3d", " -1234"}, - {"-1234", "%+8.4d", " -1234"}, - {"-1234", "%+8.5d", " -01234"}, - {"-1234", "%+8.6d", " -001234"}, - - {"1234", "% 8.3d", " 1234"}, - {"1234", "% 8.4d", " 1234"}, - {"1234", "% 8.5d", " 01234"}, - {"1234", "% 8.6d", " 001234"}, - {"-1234", "% 8.3d", " -1234"}, - {"-1234", "% 8.4d", " -1234"}, - {"-1234", "% 8.5d", " -01234"}, - {"-1234", "% 8.6d", " -001234"}, - - {"1234", "%.3x", "4d2"}, - {"1234", "%.4x", "04d2"}, - {"1234", "%.5x", "004d2"}, - {"1234", "%.6x", "0004d2"}, - {"-1234", "%.3x", "-4d2"}, - {"-1234", "%.4x", "-04d2"}, - {"-1234", "%.5x", "-004d2"}, - {"-1234", "%.6x", "-0004d2"}, - - {"1234", "%8.3x", " 4d2"}, - {"1234", "%8.4x", " 04d2"}, - {"1234", "%8.5x", " 004d2"}, - {"1234", "%8.6x", " 0004d2"}, - {"-1234", "%8.3x", " -4d2"}, - {"-1234", "%8.4x", " -04d2"}, - {"-1234", "%8.5x", " -004d2"}, - {"-1234", "%8.6x", " -0004d2"}, - - {"1234", "%+8.3x", " +4d2"}, - {"1234", "%+8.4x", " +04d2"}, - {"1234", "%+8.5x", " +004d2"}, - {"1234", "%+8.6x", " +0004d2"}, - {"-1234", "%+8.3x", " -4d2"}, - {"-1234", "%+8.4x", " -04d2"}, - {"-1234", "%+8.5x", " -004d2"}, - {"-1234", "%+8.6x", " -0004d2"}, - - {"1234", "% 8.3x", " 4d2"}, - {"1234", "% 8.4x", " 04d2"}, - {"1234", "% 8.5x", " 004d2"}, - {"1234", "% 8.6x", " 0004d2"}, - {"1234", "% 8.7x", " 00004d2"}, - {"1234", "% 8.8x", " 000004d2"}, - {"-1234", "% 8.3x", " -4d2"}, - {"-1234", "% 8.4x", " -04d2"}, - {"-1234", "% 8.5x", " -004d2"}, - {"-1234", "% 8.6x", " -0004d2"}, - {"-1234", "% 8.7x", "-00004d2"}, - {"-1234", "% 8.8x", "-000004d2"}, - - {"1234", "%-8.3d", "1234 "}, - {"1234", "%-8.4d", "1234 "}, - {"1234", "%-8.5d", "01234 "}, - {"1234", "%-8.6d", "001234 "}, - {"1234", "%-8.7d", "0001234 "}, - {"1234", "%-8.8d", "00001234"}, - {"-1234", "%-8.3d", "-1234 "}, - {"-1234", "%-8.4d", "-1234 "}, - {"-1234", "%-8.5d", "-01234 "}, - {"-1234", "%-8.6d", "-001234 "}, - {"-1234", "%-8.7d", "-0001234"}, - {"-1234", "%-8.8d", "-00001234"}, - - {"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1 - - {"0", "%.d", ""}, - {"0", "%.0d", ""}, - {"0", "%3.d", ""}, -} - -func TestFormat(t *testing.T) { - for i, test := range formatTests { - var x *Int - if test.input != "" { - var ok bool - x, ok = new(Int).SetString(test.input, 0) - if !ok { - t.Errorf("#%d failed reading input %s", i, test.input) - } - } - output := fmt.Sprintf(test.format, x) - if output != test.output { - t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output) - } - } -} - -var scanTests = []struct { - input string - format string - output string - remaining int -}{ - {"1010", "%b", "10", 0}, - {"0b1010", "%v", "10", 0}, - {"12", "%o", "10", 0}, - {"012", "%v", "10", 0}, - {"10", "%d", "10", 0}, - {"10", "%v", "10", 0}, - {"a", "%x", "10", 0}, - {"0xa", "%v", "10", 0}, - {"A", "%X", "10", 0}, - {"-A", "%X", "-10", 0}, - {"+0b1011001", "%v", "89", 0}, - {"0xA", "%v", "10", 0}, - {"0 ", "%v", "0", 1}, - {"2+3", "%v", "2", 2}, - {"0XABC 12", "%v", "2748", 3}, -} - -func TestScan(t *testing.T) { - var buf bytes.Buffer - for i, test := range scanTests { - x := new(Int) - buf.Reset() - buf.WriteString(test.input) - if _, err := fmt.Fscanf(&buf, test.format, x); err != nil { - t.Errorf("#%d error: %s", i, err) - } - if x.String() != test.output { - t.Errorf("#%d got %s; want %s", i, x.String(), test.output) - } - if buf.Len() != test.remaining { - t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining) - } - } -} - -// Examples from the Go Language Spec, section "Arithmetic operators" -var divisionSignsTests = []struct { - x, y int64 - q, r int64 // T-division - d, m int64 // Euclidian division -}{ - {5, 3, 1, 2, 1, 2}, - {-5, 3, -1, -2, -2, 1}, - {5, -3, -1, 2, -1, 2}, - {-5, -3, 1, -2, 2, 1}, - {1, 2, 0, 1, 0, 1}, - {8, 4, 2, 0, 2, 0}, -} - -func TestDivisionSigns(t *testing.T) { - for i, test := range divisionSignsTests { - x := NewInt(test.x) - y := NewInt(test.y) - q := NewInt(test.q) - r := NewInt(test.r) - d := NewInt(test.d) - m := NewInt(test.m) - - q1 := new(Int).Quo(x, y) - r1 := new(Int).Rem(x, y) - if !isNormalized(q1) { - t.Errorf("#%d Quo: %v is not normalized", i, *q1) - } - if !isNormalized(r1) { - t.Errorf("#%d Rem: %v is not normalized", i, *r1) - } - if q1.Cmp(q) != 0 || r1.Cmp(r) != 0 { - t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q1, r1, q, r) - } - - q2, r2 := new(Int).QuoRem(x, y, new(Int)) - if !isNormalized(q2) { - t.Errorf("#%d Quo: %v is not normalized", i, *q2) - } - if !isNormalized(r2) { - t.Errorf("#%d Rem: %v is not normalized", i, *r2) - } - if q2.Cmp(q) != 0 || r2.Cmp(r) != 0 { - t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q2, r2, q, r) - } - - d1 := new(Int).Div(x, y) - m1 := new(Int).Mod(x, y) - if !isNormalized(d1) { - t.Errorf("#%d Div: %v is not normalized", i, *d1) - } - if !isNormalized(m1) { - t.Errorf("#%d Mod: %v is not normalized", i, *m1) - } - if d1.Cmp(d) != 0 || m1.Cmp(m) != 0 { - t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d1, m1, d, m) - } - - d2, m2 := new(Int).DivMod(x, y, new(Int)) - if !isNormalized(d2) { - t.Errorf("#%d Div: %v is not normalized", i, *d2) - } - if !isNormalized(m2) { - t.Errorf("#%d Mod: %v is not normalized", i, *m2) - } - if d2.Cmp(d) != 0 || m2.Cmp(m) != 0 { - t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d2, m2, d, m) - } - } -} - -func checkSetBytes(b []byte) bool { - hex1 := hex.EncodeToString(new(Int).SetBytes(b).Bytes()) - hex2 := hex.EncodeToString(b) - - for len(hex1) < len(hex2) { - hex1 = "0" + hex1 - } - - for len(hex1) > len(hex2) { - hex2 = "0" + hex2 - } - - return hex1 == hex2 -} - -func TestSetBytes(t *testing.T) { - if err := quick.Check(checkSetBytes, nil); err != nil { - t.Error(err) - } -} - -func checkBytes(b []byte) bool { - b2 := new(Int).SetBytes(b).Bytes() - return bytes.Compare(b, b2) == 0 -} - -func TestBytes(t *testing.T) { - if err := quick.Check(checkSetBytes, nil); err != nil { - t.Error(err) - } -} - -func checkQuo(x, y []byte) bool { - u := new(Int).SetBytes(x) - v := new(Int).SetBytes(y) - - if len(v.abs) == 0 { - return true - } - - r := new(Int) - q, r := new(Int).QuoRem(u, v, r) - - if r.Cmp(v) >= 0 { - return false - } - - uprime := new(Int).Set(q) - uprime.Mul(uprime, v) - uprime.Add(uprime, r) - - return uprime.Cmp(u) == 0 -} - -var quoTests = []struct { - x, y string - q, r string -}{ - { - "476217953993950760840509444250624797097991362735329973741718102894495832294430498335824897858659711275234906400899559094370964723884706254265559534144986498357", - "9353930466774385905609975137998169297361893554149986716853295022578535724979483772383667534691121982974895531435241089241440253066816724367338287092081996", - "50911", - "1", - }, - { - "11510768301994997771168", - "1328165573307167369775", - "8", - "885443715537658812968", - }, -} - -func TestQuo(t *testing.T) { - if err := quick.Check(checkQuo, nil); err != nil { - t.Error(err) - } - - for i, test := range quoTests { - x, _ := new(Int).SetString(test.x, 10) - y, _ := new(Int).SetString(test.y, 10) - expectedQ, _ := new(Int).SetString(test.q, 10) - expectedR, _ := new(Int).SetString(test.r, 10) - - r := new(Int) - q, r := new(Int).QuoRem(x, y, r) - - if q.Cmp(expectedQ) != 0 || r.Cmp(expectedR) != 0 { - t.Errorf("#%d got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR) - } - } -} - -func TestQuoStepD6(t *testing.T) { - // See Knuth, Volume 2, section 4.3.1, exercise 21. This code exercises - // a code path which only triggers 1 in 10^{-19} cases. - - u := &Int{false, nat{0, 0, 1 + 1<<(_W-1), _M ^ (1 << (_W - 1))}} - v := &Int{false, nat{5, 2 + 1<<(_W-1), 1 << (_W - 1)}} - - r := new(Int) - q, r := new(Int).QuoRem(u, v, r) - const expectedQ64 = "18446744073709551613" - const expectedR64 = "3138550867693340382088035895064302439801311770021610913807" - const expectedQ32 = "4294967293" - const expectedR32 = "39614081266355540837921718287" - if q.String() != expectedQ64 && q.String() != expectedQ32 || - r.String() != expectedR64 && r.String() != expectedR32 { - t.Errorf("got (%s, %s) want (%s, %s) or (%s, %s)", q, r, expectedQ64, expectedR64, expectedQ32, expectedR32) - } -} - -var bitLenTests = []struct { - in string - out int -}{ - {"-1", 1}, - {"0", 0}, - {"1", 1}, - {"2", 2}, - {"4", 3}, - {"0xabc", 12}, - {"0x8000", 16}, - {"0x80000000", 32}, - {"0x800000000000", 48}, - {"0x8000000000000000", 64}, - {"0x80000000000000000000", 80}, - {"-0x4000000000000000000000", 87}, -} - -func TestBitLen(t *testing.T) { - for i, test := range bitLenTests { - x, ok := new(Int).SetString(test.in, 0) - if !ok { - t.Errorf("#%d test input invalid: %s", i, test.in) - continue - } - - if n := x.BitLen(); n != test.out { - t.Errorf("#%d got %d want %d", i, n, test.out) - } - } -} - -var expTests = []struct { - x, y, m string - out string -}{ - {"5", "0", "", "1"}, - {"-5", "0", "", "-1"}, - {"5", "1", "", "5"}, - {"-5", "1", "", "-5"}, - {"-2", "3", "2", "0"}, - {"5", "2", "", "25"}, - {"1", "65537", "2", "1"}, - {"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"}, - {"0x8000000000000000", "2", "6719", "4944"}, - {"0x8000000000000000", "3", "6719", "5447"}, - {"0x8000000000000000", "1000", "6719", "1603"}, - {"0x8000000000000000", "1000000", "6719", "3199"}, - { - "2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347", - "298472983472983471903246121093472394872319615612417471234712061", - "29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464", - "23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291", - }, -} - -func TestExp(t *testing.T) { - for i, test := range expTests { - x, ok1 := new(Int).SetString(test.x, 0) - y, ok2 := new(Int).SetString(test.y, 0) - out, ok3 := new(Int).SetString(test.out, 0) - - var ok4 bool - var m *Int - - if len(test.m) == 0 { - m, ok4 = nil, true - } else { - m, ok4 = new(Int).SetString(test.m, 0) - } - - if !ok1 || !ok2 || !ok3 || !ok4 { - t.Errorf("#%d: error in input", i) - continue - } - - z := y.Exp(x, y, m) - if !isNormalized(z) { - t.Errorf("#%d: %v is not normalized", i, *z) - } - if z.Cmp(out) != 0 { - t.Errorf("#%d: got %s want %s", i, z, out) - } - } -} - -func checkGcd(aBytes, bBytes []byte) bool { - a := new(Int).SetBytes(aBytes) - b := new(Int).SetBytes(bBytes) - - x := new(Int) - y := new(Int) - d := new(Int) - - GcdInt(d, x, y, a, b) - x.Mul(x, a) - y.Mul(y, b) - x.Add(x, y) - - return x.Cmp(d) == 0 -} - -var gcdTests = []struct { - a, b int64 - d, x, y int64 -}{ - {120, 23, 1, -9, 47}, -} - -func TestGcd(t *testing.T) { - for i, test := range gcdTests { - a := NewInt(test.a) - b := NewInt(test.b) - - x := new(Int) - y := new(Int) - d := new(Int) - - expectedX := NewInt(test.x) - expectedY := NewInt(test.y) - expectedD := NewInt(test.d) - - GcdInt(d, x, y, a, b) - - if expectedX.Cmp(x) != 0 || - expectedY.Cmp(y) != 0 || - expectedD.Cmp(d) != 0 { - t.Errorf("#%d got (%s %s %s) want (%s %s %s)", i, x, y, d, expectedX, expectedY, expectedD) - } - } - - quick.Check(checkGcd, nil) -} - -var primes = []string{ - "2", - "3", - "5", - "7", - "11", - - "13756265695458089029", - "13496181268022124907", - "10953742525620032441", - "17908251027575790097", - - // http://code.google.com/p/go/issues/detail?id=638 - "18699199384836356663", - - "98920366548084643601728869055592650835572950932266967461790948584315647051443", - "94560208308847015747498523884063394671606671904944666360068158221458669711639", - - // http://primes.utm.edu/lists/small/small3.html - "449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163", - "230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593", - "5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993", - "203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123", -} - -var composites = []string{ - "21284175091214687912771199898307297748211672914763848041968395774954376176754", - "6084766654921918907427900243509372380954290099172559290432744450051395395951", - "84594350493221918389213352992032324280367711247940675652888030554255915464401", - "82793403787388584738507275144194252681", -} - -func TestProbablyPrime(t *testing.T) { - nreps := 20 - if testing.Short() { - nreps = 1 - } - for i, s := range primes { - p, _ := new(Int).SetString(s, 10) - if !ProbablyPrime(p, nreps) { - t.Errorf("#%d prime found to be non-prime (%s)", i, s) - } - } - - for i, s := range composites { - c, _ := new(Int).SetString(s, 10) - if ProbablyPrime(c, nreps) { - t.Errorf("#%d composite found to be prime (%s)", i, s) - } - if testing.Short() { - break - } - } -} - -type intShiftTest struct { - in string - shift uint - out string -} - -var rshTests = []intShiftTest{ - {"0", 0, "0"}, - {"-0", 0, "0"}, - {"0", 1, "0"}, - {"0", 2, "0"}, - {"1", 0, "1"}, - {"1", 1, "0"}, - {"1", 2, "0"}, - {"2", 0, "2"}, - {"2", 1, "1"}, - {"-1", 0, "-1"}, - {"-1", 1, "-1"}, - {"-1", 10, "-1"}, - {"-100", 2, "-25"}, - {"-100", 3, "-13"}, - {"-100", 100, "-1"}, - {"4294967296", 0, "4294967296"}, - {"4294967296", 1, "2147483648"}, - {"4294967296", 2, "1073741824"}, - {"18446744073709551616", 0, "18446744073709551616"}, - {"18446744073709551616", 1, "9223372036854775808"}, - {"18446744073709551616", 2, "4611686018427387904"}, - {"18446744073709551616", 64, "1"}, - {"340282366920938463463374607431768211456", 64, "18446744073709551616"}, - {"340282366920938463463374607431768211456", 128, "1"}, -} - -func TestRsh(t *testing.T) { - for i, test := range rshTests { - in, _ := new(Int).SetString(test.in, 10) - expected, _ := new(Int).SetString(test.out, 10) - out := new(Int).Rsh(in, test.shift) - - if !isNormalized(out) { - t.Errorf("#%d: %v is not normalized", i, *out) - } - if out.Cmp(expected) != 0 { - t.Errorf("#%d: got %s want %s", i, out, expected) - } - } -} - -func TestRshSelf(t *testing.T) { - for i, test := range rshTests { - z, _ := new(Int).SetString(test.in, 10) - expected, _ := new(Int).SetString(test.out, 10) - z.Rsh(z, test.shift) - - if !isNormalized(z) { - t.Errorf("#%d: %v is not normalized", i, *z) - } - if z.Cmp(expected) != 0 { - t.Errorf("#%d: got %s want %s", i, z, expected) - } - } -} - -var lshTests = []intShiftTest{ - {"0", 0, "0"}, - {"0", 1, "0"}, - {"0", 2, "0"}, - {"1", 0, "1"}, - {"1", 1, "2"}, - {"1", 2, "4"}, - {"2", 0, "2"}, - {"2", 1, "4"}, - {"2", 2, "8"}, - {"-87", 1, "-174"}, - {"4294967296", 0, "4294967296"}, - {"4294967296", 1, "8589934592"}, - {"4294967296", 2, "17179869184"}, - {"18446744073709551616", 0, "18446744073709551616"}, - {"9223372036854775808", 1, "18446744073709551616"}, - {"4611686018427387904", 2, "18446744073709551616"}, - {"1", 64, "18446744073709551616"}, - {"18446744073709551616", 64, "340282366920938463463374607431768211456"}, - {"1", 128, "340282366920938463463374607431768211456"}, -} - -func TestLsh(t *testing.T) { - for i, test := range lshTests { - in, _ := new(Int).SetString(test.in, 10) - expected, _ := new(Int).SetString(test.out, 10) - out := new(Int).Lsh(in, test.shift) - - if !isNormalized(out) { - t.Errorf("#%d: %v is not normalized", i, *out) - } - if out.Cmp(expected) != 0 { - t.Errorf("#%d: got %s want %s", i, out, expected) - } - } -} - -func TestLshSelf(t *testing.T) { - for i, test := range lshTests { - z, _ := new(Int).SetString(test.in, 10) - expected, _ := new(Int).SetString(test.out, 10) - z.Lsh(z, test.shift) - - if !isNormalized(z) { - t.Errorf("#%d: %v is not normalized", i, *z) - } - if z.Cmp(expected) != 0 { - t.Errorf("#%d: got %s want %s", i, z, expected) - } - } -} - -func TestLshRsh(t *testing.T) { - for i, test := range rshTests { - in, _ := new(Int).SetString(test.in, 10) - out := new(Int).Lsh(in, test.shift) - out = out.Rsh(out, test.shift) - - if !isNormalized(out) { - t.Errorf("#%d: %v is not normalized", i, *out) - } - if in.Cmp(out) != 0 { - t.Errorf("#%d: got %s want %s", i, out, in) - } - } - for i, test := range lshTests { - in, _ := new(Int).SetString(test.in, 10) - out := new(Int).Lsh(in, test.shift) - out.Rsh(out, test.shift) - - if !isNormalized(out) { - t.Errorf("#%d: %v is not normalized", i, *out) - } - if in.Cmp(out) != 0 { - t.Errorf("#%d: got %s want %s", i, out, in) - } - } -} - -var int64Tests = []int64{ - 0, - 1, - -1, - 4294967295, - -4294967295, - 4294967296, - -4294967296, - 9223372036854775807, - -9223372036854775807, - -9223372036854775808, -} - -func TestInt64(t *testing.T) { - for i, testVal := range int64Tests { - in := NewInt(testVal) - out := in.Int64() - - if out != testVal { - t.Errorf("#%d got %d want %d", i, out, testVal) - } - } -} - -var bitwiseTests = []struct { - x, y string - and, or, xor, andNot string -}{ - {"0x00", "0x00", "0x00", "0x00", "0x00", "0x00"}, - {"0x00", "0x01", "0x00", "0x01", "0x01", "0x00"}, - {"0x01", "0x00", "0x00", "0x01", "0x01", "0x01"}, - {"-0x01", "0x00", "0x00", "-0x01", "-0x01", "-0x01"}, - {"-0xaf", "-0x50", "-0xf0", "-0x0f", "0xe1", "0x41"}, - {"0x00", "-0x01", "0x00", "-0x01", "-0x01", "0x00"}, - {"0x01", "0x01", "0x01", "0x01", "0x00", "0x00"}, - {"-0x01", "-0x01", "-0x01", "-0x01", "0x00", "0x00"}, - {"0x07", "0x08", "0x00", "0x0f", "0x0f", "0x07"}, - {"0x05", "0x0f", "0x05", "0x0f", "0x0a", "0x00"}, - {"0x013ff6", "0x9a4e", "0x1a46", "0x01bffe", "0x01a5b8", "0x0125b0"}, - {"-0x013ff6", "0x9a4e", "0x800a", "-0x0125b2", "-0x01a5bc", "-0x01c000"}, - {"-0x013ff6", "-0x9a4e", "-0x01bffe", "-0x1a46", "0x01a5b8", "0x8008"}, - { - "0x1000009dc6e3d9822cba04129bcbe3401", - "0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd", - "0x1000001186210100001000009048c2001", - "0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd", - "0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc", - "0x8c40c2d8822caa04120b8321400", - }, - { - "0x1000009dc6e3d9822cba04129bcbe3401", - "-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd", - "0x8c40c2d8822caa04120b8321401", - "-0xb9bd7d543685789d57ca918e82229142459020483cd2014001fd", - "-0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fe", - "0x1000001186210100001000009048c2000", - }, - { - "-0x1000009dc6e3d9822cba04129bcbe3401", - "-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd", - "-0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd", - "-0x1000001186210100001000009048c2001", - "0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc", - "0xb9bd7d543685789d57ca918e82229142459020483cd2014001fc", - }, -} - -type bitFun func(z, x, y *Int) *Int - -func testBitFun(t *testing.T, msg string, f bitFun, x, y *Int, exp string) { - expected := new(Int) - expected.SetString(exp, 0) - - out := f(new(Int), x, y) - if out.Cmp(expected) != 0 { - t.Errorf("%s: got %s want %s", msg, out, expected) - } -} - -func testBitFunSelf(t *testing.T, msg string, f bitFun, x, y *Int, exp string) { - self := new(Int) - self.Set(x) - expected := new(Int) - expected.SetString(exp, 0) - - self = f(self, self, y) - if self.Cmp(expected) != 0 { - t.Errorf("%s: got %s want %s", msg, self, expected) - } -} - -func altBit(x *Int, i int) uint { - z := new(Int).Rsh(x, uint(i)) - z = z.And(z, NewInt(1)) - if z.Cmp(new(Int)) != 0 { - return 1 - } - return 0 -} - -func altSetBit(z *Int, x *Int, i int, b uint) *Int { - one := NewInt(1) - m := one.Lsh(one, uint(i)) - switch b { - case 1: - return z.Or(x, m) - case 0: - return z.AndNot(x, m) - } - panic("set bit is not 0 or 1") -} - -func testBitset(t *testing.T, x *Int) { - n := x.BitLen() - z := new(Int).Set(x) - z1 := new(Int).Set(x) - for i := 0; i < n+10; i++ { - old := z.Bit(i) - old1 := altBit(z1, i) - if old != old1 { - t.Errorf("bitset: inconsistent value for Bit(%s, %d), got %v want %v", z1, i, old, old1) - } - z := new(Int).SetBit(z, i, 1) - z1 := altSetBit(new(Int), z1, i, 1) - if z.Bit(i) == 0 { - t.Errorf("bitset: bit %d of %s got 0 want 1", i, x) - } - if z.Cmp(z1) != 0 { - t.Errorf("bitset: inconsistent value after SetBit 1, got %s want %s", z, z1) - } - z.SetBit(z, i, 0) - altSetBit(z1, z1, i, 0) - if z.Bit(i) != 0 { - t.Errorf("bitset: bit %d of %s got 1 want 0", i, x) - } - if z.Cmp(z1) != 0 { - t.Errorf("bitset: inconsistent value after SetBit 0, got %s want %s", z, z1) - } - altSetBit(z1, z1, i, old) - z.SetBit(z, i, old) - if z.Cmp(z1) != 0 { - t.Errorf("bitset: inconsistent value after SetBit old, got %s want %s", z, z1) - } - } - if z.Cmp(x) != 0 { - t.Errorf("bitset: got %s want %s", z, x) - } -} - -var bitsetTests = []struct { - x string - i int - b uint -}{ - {"0", 0, 0}, - {"0", 200, 0}, - {"1", 0, 1}, - {"1", 1, 0}, - {"-1", 0, 1}, - {"-1", 200, 1}, - {"0x2000000000000000000000000000", 108, 0}, - {"0x2000000000000000000000000000", 109, 1}, - {"0x2000000000000000000000000000", 110, 0}, - {"-0x2000000000000000000000000001", 108, 1}, - {"-0x2000000000000000000000000001", 109, 0}, - {"-0x2000000000000000000000000001", 110, 1}, -} - -func TestBitSet(t *testing.T) { - for _, test := range bitwiseTests { - x := new(Int) - x.SetString(test.x, 0) - testBitset(t, x) - x = new(Int) - x.SetString(test.y, 0) - testBitset(t, x) - } - for i, test := range bitsetTests { - x := new(Int) - x.SetString(test.x, 0) - b := x.Bit(test.i) - if b != test.b { - - t.Errorf("#%d want %v got %v", i, test.b, b) - } - } -} - -func BenchmarkBitset(b *testing.B) { - z := new(Int) - z.SetBit(z, 512, 1) - b.ResetTimer() - b.StartTimer() - for i := b.N - 1; i >= 0; i-- { - z.SetBit(z, i&512, 1) - } -} - -func BenchmarkBitsetNeg(b *testing.B) { - z := NewInt(-1) - z.SetBit(z, 512, 0) - b.ResetTimer() - b.StartTimer() - for i := b.N - 1; i >= 0; i-- { - z.SetBit(z, i&512, 0) - } -} - -func BenchmarkBitsetOrig(b *testing.B) { - z := new(Int) - altSetBit(z, z, 512, 1) - b.ResetTimer() - b.StartTimer() - for i := b.N - 1; i >= 0; i-- { - altSetBit(z, z, i&512, 1) - } -} - -func BenchmarkBitsetNegOrig(b *testing.B) { - z := NewInt(-1) - altSetBit(z, z, 512, 0) - b.ResetTimer() - b.StartTimer() - for i := b.N - 1; i >= 0; i-- { - altSetBit(z, z, i&512, 0) - } -} - -func TestBitwise(t *testing.T) { - x := new(Int) - y := new(Int) - for _, test := range bitwiseTests { - x.SetString(test.x, 0) - y.SetString(test.y, 0) - - testBitFun(t, "and", (*Int).And, x, y, test.and) - testBitFunSelf(t, "and", (*Int).And, x, y, test.and) - testBitFun(t, "andNot", (*Int).AndNot, x, y, test.andNot) - testBitFunSelf(t, "andNot", (*Int).AndNot, x, y, test.andNot) - testBitFun(t, "or", (*Int).Or, x, y, test.or) - testBitFunSelf(t, "or", (*Int).Or, x, y, test.or) - testBitFun(t, "xor", (*Int).Xor, x, y, test.xor) - testBitFunSelf(t, "xor", (*Int).Xor, x, y, test.xor) - } -} - -var notTests = []struct { - in string - out string -}{ - {"0", "-1"}, - {"1", "-2"}, - {"7", "-8"}, - {"0", "-1"}, - {"-81910", "81909"}, - { - "298472983472983471903246121093472394872319615612417471234712061", - "-298472983472983471903246121093472394872319615612417471234712062", - }, -} - -func TestNot(t *testing.T) { - in := new(Int) - out := new(Int) - expected := new(Int) - for i, test := range notTests { - in.SetString(test.in, 10) - expected.SetString(test.out, 10) - out = out.Not(in) - if out.Cmp(expected) != 0 { - t.Errorf("#%d: got %s want %s", i, out, expected) - } - out = out.Not(out) - if out.Cmp(in) != 0 { - t.Errorf("#%d: got %s want %s", i, out, in) - } - } -} - -var modInverseTests = []struct { - element string - prime string -}{ - {"1", "7"}, - {"1", "13"}, - {"239487239847", "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919"}, -} - -func TestModInverse(t *testing.T) { - var element, prime Int - one := NewInt(1) - for i, test := range modInverseTests { - (&element).SetString(test.element, 10) - (&prime).SetString(test.prime, 10) - inverse := new(Int).ModInverse(&element, &prime) - inverse.Mul(inverse, &element) - inverse.Mod(inverse, &prime) - if inverse.Cmp(one) != 0 { - t.Errorf("#%d: failed (e·e^(-1)=%s)", i, inverse) - } - } -} - -// used by TestIntGobEncoding and TestRatGobEncoding -var gobEncodingTests = []string{ - "0", - "1", - "2", - "10", - "42", - "1234567890", - "298472983472983471903246121093472394872319615612417471234712061", -} - -func TestIntGobEncoding(t *testing.T) { - var medium bytes.Buffer - enc := gob.NewEncoder(&medium) - dec := gob.NewDecoder(&medium) - for i, test := range gobEncodingTests { - for j := 0; j < 2; j++ { - medium.Reset() // empty buffer for each test case (in case of failures) - stest := test - if j != 0 { - // negative numbers - stest = "-" + test - } - var tx Int - tx.SetString(stest, 10) - if err := enc.Encode(&tx); err != nil { - t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err) - } - var rx Int - if err := dec.Decode(&rx); err != nil { - t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err) - } - if rx.Cmp(&tx) != 0 { - t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx) - } - } - } -} diff --git a/libgo/go/big/nat.go b/libgo/go/big/nat.go deleted file mode 100644 index a46f782..0000000 --- a/libgo/go/big/nat.go +++ /dev/null @@ -1,1271 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package big implements multi-precision arithmetic (big numbers). -// The following numeric types are supported: -// -// - Int signed integers -// - Rat rational numbers -// -// All methods on Int take the result as the receiver; if it is one -// of the operands it may be overwritten (and its memory reused). -// To enable chaining of operations, the result is also returned. -// -package big - -// This file contains operations on unsigned multi-precision integers. -// These are the building blocks for the operations on signed integers -// and rationals. - -import ( - "errors" - "io" - "rand" -) - -// An unsigned integer x of the form -// -// x = x[n-1]*_B^(n-1) + x[n-2]*_B^(n-2) + ... + x[1]*_B + x[0] -// -// with 0 <= x[i] < _B and 0 <= i < n is stored in a slice of length n, -// with the digits x[i] as the slice elements. -// -// A number is normalized if the slice contains no leading 0 digits. -// During arithmetic operations, denormalized values may occur but are -// always normalized before returning the final result. The normalized -// representation of 0 is the empty or nil slice (length = 0). -// -type nat []Word - -var ( - natOne = nat{1} - natTwo = nat{2} - natTen = nat{10} -) - -func (z nat) clear() { - for i := range z { - z[i] = 0 - } -} - -func (z nat) norm() nat { - i := len(z) - for i > 0 && z[i-1] == 0 { - i-- - } - return z[0:i] -} - -func (z nat) make(n int) nat { - if n <= cap(z) { - return z[0:n] // reuse z - } - // Choosing a good value for e has significant performance impact - // because it increases the chance that a value can be reused. - const e = 4 // extra capacity - return make(nat, n, n+e) -} - -func (z nat) setWord(x Word) nat { - if x == 0 { - return z.make(0) - } - z = z.make(1) - z[0] = x - return z -} - -func (z nat) setUint64(x uint64) nat { - // single-digit values - if w := Word(x); uint64(w) == x { - return z.setWord(w) - } - - // compute number of words n required to represent x - n := 0 - for t := x; t > 0; t >>= _W { - n++ - } - - // split x into n words - z = z.make(n) - for i := range z { - z[i] = Word(x & _M) - x >>= _W - } - - return z -} - -func (z nat) set(x nat) nat { - z = z.make(len(x)) - copy(z, x) - return z -} - -func (z nat) add(x, y nat) nat { - m := len(x) - n := len(y) - - switch { - case m < n: - return z.add(y, x) - case m == 0: - // n == 0 because m >= n; result is 0 - return z.make(0) - case n == 0: - // result is x - return z.set(x) - } - // m > 0 - - z = z.make(m + 1) - c := addVV(z[0:n], x, y) - if m > n { - c = addVW(z[n:m], x[n:], c) - } - z[m] = c - - return z.norm() -} - -func (z nat) sub(x, y nat) nat { - m := len(x) - n := len(y) - - switch { - case m < n: - panic("underflow") - case m == 0: - // n == 0 because m >= n; result is 0 - return z.make(0) - case n == 0: - // result is x - return z.set(x) - } - // m > 0 - - z = z.make(m) - c := subVV(z[0:n], x, y) - if m > n { - c = subVW(z[n:], x[n:], c) - } - if c != 0 { - panic("underflow") - } - - return z.norm() -} - -func (x nat) cmp(y nat) (r int) { - m := len(x) - n := len(y) - if m != n || m == 0 { - switch { - case m < n: - r = -1 - case m > n: - r = 1 - } - return - } - - i := m - 1 - for i > 0 && x[i] == y[i] { - i-- - } - - switch { - case x[i] < y[i]: - r = -1 - case x[i] > y[i]: - r = 1 - } - return -} - -func (z nat) mulAddWW(x nat, y, r Word) nat { - m := len(x) - if m == 0 || y == 0 { - return z.setWord(r) // result is r - } - // m > 0 - - z = z.make(m + 1) - z[m] = mulAddVWW(z[0:m], x, y, r) - - return z.norm() -} - -// basicMul multiplies x and y and leaves the result in z. -// The (non-normalized) result is placed in z[0 : len(x) + len(y)]. -func basicMul(z, x, y nat) { - z[0 : len(x)+len(y)].clear() // initialize z - for i, d := range y { - if d != 0 { - z[len(x)+i] = addMulVVW(z[i:i+len(x)], x, d) - } - } -} - -// Fast version of z[0:n+n>>1].add(z[0:n+n>>1], x[0:n]) w/o bounds checks. -// Factored out for readability - do not use outside karatsuba. -func karatsubaAdd(z, x nat, n int) { - if c := addVV(z[0:n], z, x); c != 0 { - addVW(z[n:n+n>>1], z[n:], c) - } -} - -// Like karatsubaAdd, but does subtract. -func karatsubaSub(z, x nat, n int) { - if c := subVV(z[0:n], z, x); c != 0 { - subVW(z[n:n+n>>1], z[n:], c) - } -} - -// Operands that are shorter than karatsubaThreshold are multiplied using -// "grade school" multiplication; for longer operands the Karatsuba algorithm -// is used. -var karatsubaThreshold int = 32 // computed by calibrate.go - -// karatsuba multiplies x and y and leaves the result in z. -// Both x and y must have the same length n and n must be a -// power of 2. The result vector z must have len(z) >= 6*n. -// The (non-normalized) result is placed in z[0 : 2*n]. -func karatsuba(z, x, y nat) { - n := len(y) - - // Switch to basic multiplication if numbers are odd or small. - // (n is always even if karatsubaThreshold is even, but be - // conservative) - if n&1 != 0 || n < karatsubaThreshold || n < 2 { - basicMul(z, x, y) - return - } - // n&1 == 0 && n >= karatsubaThreshold && n >= 2 - - // Karatsuba multiplication is based on the observation that - // for two numbers x and y with: - // - // x = x1*b + x0 - // y = y1*b + y0 - // - // the product x*y can be obtained with 3 products z2, z1, z0 - // instead of 4: - // - // x*y = x1*y1*b*b + (x1*y0 + x0*y1)*b + x0*y0 - // = z2*b*b + z1*b + z0 - // - // with: - // - // xd = x1 - x0 - // yd = y0 - y1 - // - // z1 = xd*yd + z1 + z0 - // = (x1-x0)*(y0 - y1) + z1 + z0 - // = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z1 + z0 - // = x1*y0 - z1 - z0 + x0*y1 + z1 + z0 - // = x1*y0 + x0*y1 - - // split x, y into "digits" - n2 := n >> 1 // n2 >= 1 - x1, x0 := x[n2:], x[0:n2] // x = x1*b + y0 - y1, y0 := y[n2:], y[0:n2] // y = y1*b + y0 - - // z is used for the result and temporary storage: - // - // 6*n 5*n 4*n 3*n 2*n 1*n 0*n - // z = [z2 copy|z0 copy| xd*yd | yd:xd | x1*y1 | x0*y0 ] - // - // For each recursive call of karatsuba, an unused slice of - // z is passed in that has (at least) half the length of the - // caller's z. - - // compute z0 and z2 with the result "in place" in z - karatsuba(z, x0, y0) // z0 = x0*y0 - karatsuba(z[n:], x1, y1) // z2 = x1*y1 - - // compute xd (or the negative value if underflow occurs) - s := 1 // sign of product xd*yd - xd := z[2*n : 2*n+n2] - if subVV(xd, x1, x0) != 0 { // x1-x0 - s = -s - subVV(xd, x0, x1) // x0-x1 - } - - // compute yd (or the negative value if underflow occurs) - yd := z[2*n+n2 : 3*n] - if subVV(yd, y0, y1) != 0 { // y0-y1 - s = -s - subVV(yd, y1, y0) // y1-y0 - } - - // p = (x1-x0)*(y0-y1) == x1*y0 - x1*y1 - x0*y0 + x0*y1 for s > 0 - // p = (x0-x1)*(y0-y1) == x0*y0 - x0*y1 - x1*y0 + x1*y1 for s < 0 - p := z[n*3:] - karatsuba(p, xd, yd) - - // save original z2:z0 - // (ok to use upper half of z since we're done recursing) - r := z[n*4:] - copy(r, z) - - // add up all partial products - // - // 2*n n 0 - // z = [ z2 | z0 ] - // + [ z0 ] - // + [ z2 ] - // + [ p ] - // - karatsubaAdd(z[n2:], r, n) - karatsubaAdd(z[n2:], r[n:], n) - if s > 0 { - karatsubaAdd(z[n2:], p, n) - } else { - karatsubaSub(z[n2:], p, n) - } -} - -// alias returns true if x and y share the same base array. -func alias(x, y nat) bool { - return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1] -} - -// addAt implements z += x*(1<<(_W*i)); z must be long enough. -// (we don't use nat.add because we need z to stay the same -// slice, and we don't need to normalize z after each addition) -func addAt(z, x nat, i int) { - if n := len(x); n > 0 { - if c := addVV(z[i:i+n], z[i:], x); c != 0 { - j := i + n - if j < len(z) { - addVW(z[j:], z[j:], c) - } - } - } -} - -func max(x, y int) int { - if x > y { - return x - } - return y -} - -// karatsubaLen computes an approximation to the maximum k <= n such that -// k = p<= 0. Thus, the -// result is the largest number that can be divided repeatedly by 2 before -// becoming about the value of karatsubaThreshold. -func karatsubaLen(n int) int { - i := uint(0) - for n > karatsubaThreshold { - n >>= 1 - i++ - } - return n << i -} - -func (z nat) mul(x, y nat) nat { - m := len(x) - n := len(y) - - switch { - case m < n: - return z.mul(y, x) - case m == 0 || n == 0: - return z.make(0) - case n == 1: - return z.mulAddWW(x, y[0], 0) - } - // m >= n > 1 - - // determine if z can be reused - if alias(z, x) || alias(z, y) { - z = nil // z is an alias for x or y - cannot reuse - } - - // use basic multiplication if the numbers are small - if n < karatsubaThreshold || n < 2 { - z = z.make(m + n) - basicMul(z, x, y) - return z.norm() - } - // m >= n && n >= karatsubaThreshold && n >= 2 - - // determine Karatsuba length k such that - // - // x = x1*b + x0 - // y = y1*b + y0 (and k <= len(y), which implies k <= len(x)) - // b = 1<<(_W*k) ("base" of digits xi, yi) - // - k := karatsubaLen(n) - // k <= n - - // multiply x0 and y0 via Karatsuba - x0 := x[0:k] // x0 is not normalized - y0 := y[0:k] // y0 is not normalized - z = z.make(max(6*k, m+n)) // enough space for karatsuba of x0*y0 and full result of x*y - karatsuba(z, x0, y0) - z = z[0 : m+n] // z has final length but may be incomplete, upper portion is garbage - - // If x1 and/or y1 are not 0, add missing terms to z explicitly: - // - // m+n 2*k 0 - // z = [ ... | x0*y0 ] - // + [ x1*y1 ] - // + [ x1*y0 ] - // + [ x0*y1 ] - // - if k < n || m != n { - x1 := x[k:] // x1 is normalized because x is - y1 := y[k:] // y1 is normalized because y is - var t nat - t = t.mul(x1, y1) - copy(z[2*k:], t) - z[2*k+len(t):].clear() // upper portion of z is garbage - t = t.mul(x1, y0.norm()) - addAt(z, t, k) - t = t.mul(x0.norm(), y1) - addAt(z, t, k) - } - - return z.norm() -} - -// mulRange computes the product of all the unsigned integers in the -// range [a, b] inclusively. If a > b (empty range), the result is 1. -func (z nat) mulRange(a, b uint64) nat { - switch { - case a == 0: - // cut long ranges short (optimization) - return z.setUint64(0) - case a > b: - return z.setUint64(1) - case a == b: - return z.setUint64(a) - case a+1 == b: - return z.mul(nat{}.setUint64(a), nat{}.setUint64(b)) - } - m := (a + b) / 2 - return z.mul(nat{}.mulRange(a, m), nat{}.mulRange(m+1, b)) -} - -// q = (x-r)/y, with 0 <= r < y -func (z nat) divW(x nat, y Word) (q nat, r Word) { - m := len(x) - switch { - case y == 0: - panic("division by zero") - case y == 1: - q = z.set(x) // result is x - return - case m == 0: - q = z.make(0) // result is 0 - return - } - // m > 0 - z = z.make(m) - r = divWVW(z, 0, x, y) - q = z.norm() - return -} - -func (z nat) div(z2, u, v nat) (q, r nat) { - if len(v) == 0 { - panic("division by zero") - } - - if u.cmp(v) < 0 { - q = z.make(0) - r = z2.set(u) - return - } - - if len(v) == 1 { - var rprime Word - q, rprime = z.divW(u, v[0]) - if rprime > 0 { - r = z2.make(1) - r[0] = rprime - } else { - r = z2.make(0) - } - return - } - - q, r = z.divLarge(z2, u, v) - return -} - -// q = (uIn-r)/v, with 0 <= r < y -// Uses z as storage for q, and u as storage for r if possible. -// See Knuth, Volume 2, section 4.3.1, Algorithm D. -// Preconditions: -// len(v) >= 2 -// len(uIn) >= len(v) -func (z nat) divLarge(u, uIn, v nat) (q, r nat) { - n := len(v) - m := len(uIn) - n - - // determine if z can be reused - // TODO(gri) should find a better solution - this if statement - // is very costly (see e.g. time pidigits -s -n 10000) - if alias(z, uIn) || alias(z, v) { - z = nil // z is an alias for uIn or v - cannot reuse - } - q = z.make(m + 1) - - qhatv := make(nat, n+1) - if alias(u, uIn) || alias(u, v) { - u = nil // u is an alias for uIn or v - cannot reuse - } - u = u.make(len(uIn) + 1) - u.clear() - - // D1. - shift := leadingZeros(v[n-1]) - if shift > 0 { - // do not modify v, it may be used by another goroutine simultaneously - v1 := make(nat, n) - shlVU(v1, v, shift) - v = v1 - } - u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift) - - // D2. - for j := m; j >= 0; j-- { - // D3. - qhat := Word(_M) - if u[j+n] != v[n-1] { - var rhat Word - qhat, rhat = divWW(u[j+n], u[j+n-1], v[n-1]) - - // x1 | x2 = q̂v_{n-2} - x1, x2 := mulWW(qhat, v[n-2]) - // test if q̂v_{n-2} > br̂ + u_{j+n-2} - for greaterThan(x1, x2, rhat, u[j+n-2]) { - qhat-- - prevRhat := rhat - rhat += v[n-1] - // v[n-1] >= 0, so this tests for overflow. - if rhat < prevRhat { - break - } - x1, x2 = mulWW(qhat, v[n-2]) - } - } - - // D4. - qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0) - - c := subVV(u[j:j+len(qhatv)], u[j:], qhatv) - if c != 0 { - c := addVV(u[j:j+n], u[j:], v) - u[j+n] += c - qhat-- - } - - q[j] = qhat - } - - q = q.norm() - shrVU(u, u, shift) - r = u.norm() - - return q, r -} - -// Length of x in bits. x must be normalized. -func (x nat) bitLen() int { - if i := len(x) - 1; i >= 0 { - return i*_W + bitLen(x[i]) - } - return 0 -} - -// MaxBase is the largest number base accepted for string conversions. -const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1 - -func hexValue(ch rune) Word { - d := MaxBase + 1 // illegal base - switch { - case '0' <= ch && ch <= '9': - d = int(ch - '0') - case 'a' <= ch && ch <= 'z': - d = int(ch - 'a' + 10) - case 'A' <= ch && ch <= 'Z': - d = int(ch - 'A' + 10) - } - return Word(d) -} - -// scan sets z to the natural number corresponding to the longest possible prefix -// read from r representing an unsigned integer in a given conversion base. -// It returns z, the actual conversion base used, and an error, if any. In the -// error case, the value of z is undefined. The syntax follows the syntax of -// unsigned integer literals in Go. -// -// The base argument must be 0 or a value from 2 through MaxBase. If the base -// is 0, the string prefix determines the actual conversion base. A prefix of -// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a -// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10. -// -func (z nat) scan(r io.RuneScanner, base int) (nat, int, error) { - // reject illegal bases - if base < 0 || base == 1 || MaxBase < base { - return z, 0, errors.New("illegal number base") - } - - // one char look-ahead - ch, _, err := r.ReadRune() - if err != nil { - return z, 0, err - } - - // determine base if necessary - b := Word(base) - if base == 0 { - b = 10 - if ch == '0' { - switch ch, _, err = r.ReadRune(); err { - case nil: - b = 8 - switch ch { - case 'x', 'X': - b = 16 - case 'b', 'B': - b = 2 - } - if b == 2 || b == 16 { - if ch, _, err = r.ReadRune(); err != nil { - return z, 0, err - } - } - case io.EOF: - return z.make(0), 10, nil - default: - return z, 10, err - } - } - } - - // convert string - // - group as many digits d as possible together into a "super-digit" dd with "super-base" bb - // - only when bb does not fit into a word anymore, do a full number mulAddWW using bb and dd - z = z.make(0) - bb := Word(1) - dd := Word(0) - for max := _M / b; ; { - d := hexValue(ch) - if d >= b { - r.UnreadRune() // ch does not belong to number anymore - break - } - - if bb <= max { - bb *= b - dd = dd*b + d - } else { - // bb * b would overflow - z = z.mulAddWW(z, bb, dd) - bb = b - dd = d - } - - if ch, _, err = r.ReadRune(); err != nil { - if err != io.EOF { - return z, int(b), err - } - break - } - } - - switch { - case bb > 1: - // there was at least one mantissa digit - z = z.mulAddWW(z, bb, dd) - case base == 0 && b == 8: - // there was only the octal prefix 0 (possibly followed by digits > 7); - // return base 10, not 8 - return z, 10, nil - case base != 0 || b != 8: - // there was neither a mantissa digit nor the octal prefix 0 - return z, int(b), errors.New("syntax error scanning number") - } - - return z.norm(), int(b), nil -} - -// Character sets for string conversion. -const ( - lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz" - uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" -) - -// decimalString returns a decimal representation of x. -// It calls x.string with the charset "0123456789". -func (x nat) decimalString() string { - return x.string(lowercaseDigits[0:10]) -} - -// string converts x to a string using digits from a charset; a digit with -// value d is represented by charset[d]. The conversion base is determined -// by len(charset), which must be >= 2. -func (x nat) string(charset string) string { - b := Word(len(charset)) - - // special cases - switch { - case b < 2 || b > 256: - panic("illegal base") - case len(x) == 0: - return string(charset[0]) - } - - // allocate buffer for conversion - i := x.bitLen()/log2(b) + 1 // +1: round up - s := make([]byte, i) - - // special case: power of two bases can avoid divisions completely - if b == b&-b { - // shift is base-b digit size in bits - shift := uint(trailingZeroBits(b)) // shift > 0 because b >= 2 - mask := Word(1)<= shift { - i-- - s[i] = charset[w&mask] - w >>= shift - nbits -= shift - } - - // convert any partial leading digit and advance to next word - if nbits == 0 { - // no partial digit remaining, just advance - w = x[k] - nbits = _W - } else { - // partial digit in current (k-1) and next (k) word - w |= x[k] << nbits - i-- - s[i] = charset[w&mask] - - // advance - w = x[k] >> (shift - nbits) - nbits = _W - (shift - nbits) - } - } - - // convert digits of most-significant word (omit leading zeros) - for nbits >= 0 && w != 0 { - i-- - s[i] = charset[w&mask] - w >>= shift - nbits -= shift - } - - return string(s[i:]) - } - - // general case: extract groups of digits by multiprecision division - - // maximize ndigits where b**ndigits < 2^_W; bb (big base) is b**ndigits - bb := Word(1) - ndigits := 0 - for max := Word(_M / b); bb <= max; bb *= b { - ndigits++ - } - - // preserve x, create local copy for use in repeated divisions - q := nat{}.set(x) - var r Word - - // convert - if b == 10 { // hard-coding for 10 here speeds this up by 1.25x - for len(q) > 0 { - // extract least significant, base bb "digit" - q, r = q.divW(q, bb) // N.B. >82% of time is here. Optimize divW - if len(q) == 0 { - // skip leading zeros in most-significant group of digits - for j := 0; j < ndigits && r != 0; j++ { - i-- - s[i] = charset[r%10] - r /= 10 - } - } else { - for j := 0; j < ndigits; j++ { - i-- - s[i] = charset[r%10] - r /= 10 - } - } - } - } else { - for len(q) > 0 { - // extract least significant group of digits - q, r = q.divW(q, bb) // N.B. >82% of time is here. Optimize divW - if len(q) == 0 { - // skip leading zeros in most-significant group of digits - for j := 0; j < ndigits && r != 0; j++ { - i-- - s[i] = charset[r%b] - r /= b - } - } else { - for j := 0; j < ndigits; j++ { - i-- - s[i] = charset[r%b] - r /= b - } - } - } - } - - return string(s[i:]) -} - -const deBruijn32 = 0x077CB531 - -var deBruijn32Lookup = []byte{ - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, -} - -const deBruijn64 = 0x03f79d71b4ca8b09 - -var deBruijn64Lookup = []byte{ - 0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, - 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, - 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, - 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, -} - -// trailingZeroBits returns the number of consecutive zero bits on the right -// side of the given Word. -// See Knuth, volume 4, section 7.3.1 -func trailingZeroBits(x Word) int { - // x & -x leaves only the right-most bit set in the word. Let k be the - // index of that bit. Since only a single bit is set, the value is two - // to the power of k. Multiplying by a power of two is equivalent to - // left shifting, in this case by k bits. The de Bruijn constant is - // such that all six bit, consecutive substrings are distinct. - // Therefore, if we have a left shifted version of this constant we can - // find by how many bits it was shifted by looking at which six bit - // substring ended up at the top of the word. - switch _W { - case 32: - return int(deBruijn32Lookup[((x&-x)*deBruijn32)>>27]) - case 64: - return int(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58]) - default: - panic("Unknown word size") - } - - return 0 -} - -// z = x << s -func (z nat) shl(x nat, s uint) nat { - m := len(x) - if m == 0 { - return z.make(0) - } - // m > 0 - - n := m + int(s/_W) - z = z.make(n + 1) - z[n] = shlVU(z[n-m:n], x, s%_W) - z[0 : n-m].clear() - - return z.norm() -} - -// z = x >> s -func (z nat) shr(x nat, s uint) nat { - m := len(x) - n := m - int(s/_W) - if n <= 0 { - return z.make(0) - } - // n > 0 - - z = z.make(n) - shrVU(z, x[m-n:], s%_W) - - return z.norm() -} - -func (z nat) setBit(x nat, i uint, b uint) nat { - j := int(i / _W) - m := Word(1) << (i % _W) - n := len(x) - switch b { - case 0: - z = z.make(n) - copy(z, x) - if j >= n { - // no need to grow - return z - } - z[j] &^= m - return z.norm() - case 1: - if j >= n { - n = j + 1 - } - z = z.make(n) - copy(z, x) - z[j] |= m - // no need to normalize - return z - } - panic("set bit is not 0 or 1") -} - -func (z nat) bit(i uint) uint { - j := int(i / _W) - if j >= len(z) { - return 0 - } - return uint(z[j] >> (i % _W) & 1) -} - -func (z nat) and(x, y nat) nat { - m := len(x) - n := len(y) - if m > n { - m = n - } - // m <= n - - z = z.make(m) - for i := 0; i < m; i++ { - z[i] = x[i] & y[i] - } - - return z.norm() -} - -func (z nat) andNot(x, y nat) nat { - m := len(x) - n := len(y) - if n > m { - n = m - } - // m >= n - - z = z.make(m) - for i := 0; i < n; i++ { - z[i] = x[i] &^ y[i] - } - copy(z[n:m], x[n:m]) - - return z.norm() -} - -func (z nat) or(x, y nat) nat { - m := len(x) - n := len(y) - s := x - if m < n { - n, m = m, n - s = y - } - // m >= n - - z = z.make(m) - for i := 0; i < n; i++ { - z[i] = x[i] | y[i] - } - copy(z[n:m], s[n:m]) - - return z.norm() -} - -func (z nat) xor(x, y nat) nat { - m := len(x) - n := len(y) - s := x - if m < n { - n, m = m, n - s = y - } - // m >= n - - z = z.make(m) - for i := 0; i < n; i++ { - z[i] = x[i] ^ y[i] - } - copy(z[n:m], s[n:m]) - - return z.norm() -} - -// greaterThan returns true iff (x1<<_W + x2) > (y1<<_W + y2) -func greaterThan(x1, x2, y1, y2 Word) bool { - return x1 > y1 || x1 == y1 && x2 > y2 -} - -// modW returns x % d. -func (x nat) modW(d Word) (r Word) { - // TODO(agl): we don't actually need to store the q value. - var q nat - q = q.make(len(x)) - return divWVW(q, 0, x, d) -} - -// powersOfTwoDecompose finds q and k with x = q * 1<= 0; i-- { - v = y[i] - - for j := 0; j < _W; j++ { - z = z.mul(z, z) - - if v&mask != 0 { - z = z.mul(z, x) - } - - if m != nil { - q, z = q.div(z, z, m) - } - - v <<= 1 - } - } - - return z -} - -// probablyPrime performs reps Miller-Rabin tests to check whether n is prime. -// If it returns true, n is prime with probability 1 - 1/4^reps. -// If it returns false, n is not prime. -func (n nat) probablyPrime(reps int) bool { - if len(n) == 0 { - return false - } - - if len(n) == 1 { - if n[0] < 2 { - return false - } - - if n[0]%2 == 0 { - return n[0] == 2 - } - - // We have to exclude these cases because we reject all - // multiples of these numbers below. - switch n[0] { - case 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53: - return true - } - } - - const primesProduct32 = 0xC0CFD797 // Π {p ∈ primes, 2 < p <= 29} - const primesProduct64 = 0xE221F97C30E94E1D // Π {p ∈ primes, 2 < p <= 53} - - var r Word - switch _W { - case 32: - r = n.modW(primesProduct32) - case 64: - r = n.modW(primesProduct64 & _M) - default: - panic("Unknown word size") - } - - if r%3 == 0 || r%5 == 0 || r%7 == 0 || r%11 == 0 || - r%13 == 0 || r%17 == 0 || r%19 == 0 || r%23 == 0 || r%29 == 0 { - return false - } - - if _W == 64 && (r%31 == 0 || r%37 == 0 || r%41 == 0 || - r%43 == 0 || r%47 == 0 || r%53 == 0) { - return false - } - - nm1 := nat{}.sub(n, natOne) - // 1<= len(z)*_S. The value of z is encoded in the -// slice buf[i:]. The number i of unused bytes at the beginning of -// buf is returned as result. -func (z nat) bytes(buf []byte) (i int) { - i = len(buf) - for _, d := range z { - for j := 0; j < _S; j++ { - i-- - buf[i] = byte(d) - d >>= 8 - } - } - - for i < len(buf) && buf[i] == 0 { - i++ - } - - return -} - -// setBytes interprets buf as the bytes of a big-endian unsigned -// integer, sets z to that value, and returns z. -func (z nat) setBytes(buf []byte) nat { - z = z.make((len(buf) + _S - 1) / _S) - - k := 0 - s := uint(0) - var d Word - for i := len(buf); i > 0; i-- { - d |= Word(buf[i-1]) << s - if s += 8; s == _S*8 { - z[k] = d - k++ - s = 0 - d = 0 - } - } - if k < len(z) { - z[k] = d - } - - return z.norm() -} diff --git a/libgo/go/big/nat_test.go b/libgo/go/big/nat_test.go deleted file mode 100644 index 041a6c4..0000000 --- a/libgo/go/big/nat_test.go +++ /dev/null @@ -1,669 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package big - -import ( - "fmt" - "io" - "strings" - "testing" -) - -var cmpTests = []struct { - x, y nat - r int -}{ - {nil, nil, 0}, - {nil, nat{}, 0}, - {nat{}, nil, 0}, - {nat{}, nat{}, 0}, - {nat{0}, nat{0}, 0}, - {nat{0}, nat{1}, -1}, - {nat{1}, nat{0}, 1}, - {nat{1}, nat{1}, 0}, - {nat{0, _M}, nat{1}, 1}, - {nat{1}, nat{0, _M}, -1}, - {nat{1, _M}, nat{0, _M}, 1}, - {nat{0, _M}, nat{1, _M}, -1}, - {nat{16, 571956, 8794, 68}, nat{837, 9146, 1, 754489}, -1}, - {nat{34986, 41, 105, 1957}, nat{56, 7458, 104, 1957}, 1}, -} - -func TestCmp(t *testing.T) { - for i, a := range cmpTests { - r := a.x.cmp(a.y) - if r != a.r { - t.Errorf("#%d got r = %v; want %v", i, r, a.r) - } - } -} - -type funNN func(z, x, y nat) nat -type argNN struct { - z, x, y nat -} - -var sumNN = []argNN{ - {}, - {nat{1}, nil, nat{1}}, - {nat{1111111110}, nat{123456789}, nat{987654321}}, - {nat{0, 0, 0, 1}, nil, nat{0, 0, 0, 1}}, - {nat{0, 0, 0, 1111111110}, nat{0, 0, 0, 123456789}, nat{0, 0, 0, 987654321}}, - {nat{0, 0, 0, 1}, nat{0, 0, _M}, nat{0, 0, 1}}, -} - -var prodNN = []argNN{ - {}, - {nil, nil, nil}, - {nil, nat{991}, nil}, - {nat{991}, nat{991}, nat{1}}, - {nat{991 * 991}, nat{991}, nat{991}}, - {nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}}, - {nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}}, - {nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}}, -} - -func TestSet(t *testing.T) { - for _, a := range sumNN { - z := nat{}.set(a.z) - if z.cmp(a.z) != 0 { - t.Errorf("got z = %v; want %v", z, a.z) - } - } -} - -func testFunNN(t *testing.T, msg string, f funNN, a argNN) { - z := f(nil, a.x, a.y) - if z.cmp(a.z) != 0 { - t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z) - } -} - -func TestFunNN(t *testing.T) { - for _, a := range sumNN { - arg := a - testFunNN(t, "add", nat.add, arg) - - arg = argNN{a.z, a.y, a.x} - testFunNN(t, "add symmetric", nat.add, arg) - - arg = argNN{a.x, a.z, a.y} - testFunNN(t, "sub", nat.sub, arg) - - arg = argNN{a.y, a.z, a.x} - testFunNN(t, "sub symmetric", nat.sub, arg) - } - - for _, a := range prodNN { - arg := a - testFunNN(t, "mul", nat.mul, arg) - - arg = argNN{a.z, a.y, a.x} - testFunNN(t, "mul symmetric", nat.mul, arg) - } -} - -var mulRangesN = []struct { - a, b uint64 - prod string -}{ - {0, 0, "0"}, - {1, 1, "1"}, - {1, 2, "2"}, - {1, 3, "6"}, - {10, 10, "10"}, - {0, 100, "0"}, - {0, 1e9, "0"}, - {1, 0, "1"}, // empty range - {100, 1, "1"}, // empty range - {1, 10, "3628800"}, // 10! - {1, 20, "2432902008176640000"}, // 20! - {1, 100, - "933262154439441526816992388562667004907159682643816214685929" + - "638952175999932299156089414639761565182862536979208272237582" + - "51185210916864000000000000000000000000", // 100! - }, -} - -func TestMulRangeN(t *testing.T) { - for i, r := range mulRangesN { - prod := nat{}.mulRange(r.a, r.b).decimalString() - if prod != r.prod { - t.Errorf("#%d: got %s; want %s", i, prod, r.prod) - } - } -} - -var mulArg, mulTmp nat - -func init() { - const n = 1000 - mulArg = make(nat, n) - for i := 0; i < n; i++ { - mulArg[i] = _M - } -} - -func benchmarkMulLoad() { - for j := 1; j <= 10; j++ { - x := mulArg[0 : j*100] - mulTmp.mul(x, x) - } -} - -func BenchmarkMul(b *testing.B) { - for i := 0; i < b.N; i++ { - benchmarkMulLoad() - } -} - -func toString(x nat, charset string) string { - base := len(charset) - - // special cases - switch { - case base < 2: - panic("illegal base") - case len(x) == 0: - return string(charset[0]) - } - - // allocate buffer for conversion - i := x.bitLen()/log2(Word(base)) + 1 // +1: round up - s := make([]byte, i) - - // don't destroy x - q := nat{}.set(x) - - // convert - for len(q) > 0 { - i-- - var r Word - q, r = q.divW(q, Word(base)) - s[i] = charset[r] - } - - return string(s[i:]) -} - -var strTests = []struct { - x nat // nat value to be converted - c string // conversion charset - s string // expected result -}{ - {nil, "01", "0"}, - {nat{1}, "01", "1"}, - {nat{0xc5}, "01", "11000101"}, - {nat{03271}, lowercaseDigits[0:8], "3271"}, - {nat{10}, lowercaseDigits[0:10], "10"}, - {nat{1234567890}, uppercaseDigits[0:10], "1234567890"}, - {nat{0xdeadbeef}, lowercaseDigits[0:16], "deadbeef"}, - {nat{0xdeadbeef}, uppercaseDigits[0:16], "DEADBEEF"}, - {nat{0x229be7}, lowercaseDigits[0:17], "1a2b3c"}, - {nat{0x309663e6}, uppercaseDigits[0:32], "O9COV6"}, -} - -func TestString(t *testing.T) { - for _, a := range strTests { - s := a.x.string(a.c) - if s != a.s { - t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s) - } - - x, b, err := nat{}.scan(strings.NewReader(a.s), len(a.c)) - if x.cmp(a.x) != 0 { - t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x) - } - if b != len(a.c) { - t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c)) - } - if err != nil { - t.Errorf("scan%+v\n\tgot error = %s", a, err) - } - } -} - -var natScanTests = []struct { - s string // string to be scanned - base int // input base - x nat // expected nat - b int // expected base - ok bool // expected success - next rune // next character (or 0, if at EOF) -}{ - // error: illegal base - {base: -1}, - {base: 1}, - {base: 37}, - - // error: no mantissa - {}, - {s: "?"}, - {base: 10}, - {base: 36}, - {s: "?", base: 10}, - {s: "0x"}, - {s: "345", base: 2}, - - // no errors - {"0", 0, nil, 10, true, 0}, - {"0", 10, nil, 10, true, 0}, - {"0", 36, nil, 36, true, 0}, - {"1", 0, nat{1}, 10, true, 0}, - {"1", 10, nat{1}, 10, true, 0}, - {"0 ", 0, nil, 10, true, ' '}, - {"08", 0, nil, 10, true, '8'}, - {"018", 0, nat{1}, 8, true, '8'}, - {"0b1", 0, nat{1}, 2, true, 0}, - {"0b11000101", 0, nat{0xc5}, 2, true, 0}, - {"03271", 0, nat{03271}, 8, true, 0}, - {"10ab", 0, nat{10}, 10, true, 'a'}, - {"1234567890", 0, nat{1234567890}, 10, true, 0}, - {"xyz", 36, nat{(33*36+34)*36 + 35}, 36, true, 0}, - {"xyz?", 36, nat{(33*36+34)*36 + 35}, 36, true, '?'}, - {"0x", 16, nil, 16, true, 'x'}, - {"0xdeadbeef", 0, nat{0xdeadbeef}, 16, true, 0}, - {"0XDEADBEEF", 0, nat{0xdeadbeef}, 16, true, 0}, -} - -func TestScanBase(t *testing.T) { - for _, a := range natScanTests { - r := strings.NewReader(a.s) - x, b, err := nat{}.scan(r, a.base) - if err == nil && !a.ok { - t.Errorf("scan%+v\n\texpected error", a) - } - if err != nil { - if a.ok { - t.Errorf("scan%+v\n\tgot error = %s", a, err) - } - continue - } - if x.cmp(a.x) != 0 { - t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x) - } - if b != a.b { - t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base) - } - next, _, err := r.ReadRune() - if err == io.EOF { - next = 0 - err = nil - } - if err == nil && next != a.next { - t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next) - } - } -} - -var pi = "3" + - "14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" + - "32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" + - "28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" + - "96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" + - "31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" + - "60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" + - "22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" + - "29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" + - "81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" + - "21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" + - "55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" + - "63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" + - "75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" + - "45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" + - "34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" + - "16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" + - "04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" + - "26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" + - "99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" + - "53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" + - "68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" + - "13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" + - "88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" + - "79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" + - "68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" + - "21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" + - "06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" + - "14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" + - "21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" + - "05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" + - "23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" + - "90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" + - "31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" + - "20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" + - "97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" + - "44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" + - "44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" + - "85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" + - "58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" + - "27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" + - "09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" + - "79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" + - "06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" + - "91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" + - "94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" + - "78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" + - "24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" + - "59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" + - "34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" + - "88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" + - "94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337" - -// Test case for BenchmarkScanPi. -func TestScanPi(t *testing.T) { - var x nat - z, _, err := x.scan(strings.NewReader(pi), 10) - if err != nil { - t.Errorf("scanning pi: %s", err) - } - if s := z.decimalString(); s != pi { - t.Errorf("scanning pi: got %s", s) - } -} - -func BenchmarkScanPi(b *testing.B) { - for i := 0; i < b.N; i++ { - var x nat - x.scan(strings.NewReader(pi), 10) - } -} - -const ( - // 314**271 - // base 2: 2249 digits - // base 8: 751 digits - // base 10: 678 digits - // base 16: 563 digits - shortBase = 314 - shortExponent = 271 - - // 3141**2178 - // base 2: 31577 digits - // base 8: 10527 digits - // base 10: 9507 digits - // base 16: 7895 digits - mediumBase = 3141 - mediumExponent = 2718 - - // 3141**2178 - // base 2: 406078 digits - // base 8: 135360 digits - // base 10: 122243 digits - // base 16: 101521 digits - longBase = 31415 - longExponent = 27182 -) - -func BenchmarkScanShort2(b *testing.B) { - ScanHelper(b, 2, shortBase, shortExponent) -} - -func BenchmarkScanShort8(b *testing.B) { - ScanHelper(b, 8, shortBase, shortExponent) -} - -func BenchmarkScanSort10(b *testing.B) { - ScanHelper(b, 10, shortBase, shortExponent) -} - -func BenchmarkScanShort16(b *testing.B) { - ScanHelper(b, 16, shortBase, shortExponent) -} - -func BenchmarkScanMedium2(b *testing.B) { - ScanHelper(b, 2, mediumBase, mediumExponent) -} - -func BenchmarkScanMedium8(b *testing.B) { - ScanHelper(b, 8, mediumBase, mediumExponent) -} - -func BenchmarkScanMedium10(b *testing.B) { - ScanHelper(b, 10, mediumBase, mediumExponent) -} - -func BenchmarkScanMedium16(b *testing.B) { - ScanHelper(b, 16, mediumBase, mediumExponent) -} - -func BenchmarkScanLong2(b *testing.B) { - ScanHelper(b, 2, longBase, longExponent) -} - -func BenchmarkScanLong8(b *testing.B) { - ScanHelper(b, 8, longBase, longExponent) -} - -func BenchmarkScanLong10(b *testing.B) { - ScanHelper(b, 10, longBase, longExponent) -} - -func BenchmarkScanLong16(b *testing.B) { - ScanHelper(b, 16, longBase, longExponent) -} - -func ScanHelper(b *testing.B, base int, xv, yv Word) { - b.StopTimer() - var x, y, z nat - x = x.setWord(xv) - y = y.setWord(yv) - z = z.expNN(x, y, nil) - - var s string - s = z.string(lowercaseDigits[0:base]) - if t := toString(z, lowercaseDigits[0:base]); t != s { - panic(fmt.Sprintf("scanning: got %s; want %s", s, t)) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - x.scan(strings.NewReader(s), base) - } -} - -func BenchmarkStringShort2(b *testing.B) { - StringHelper(b, 2, shortBase, shortExponent) -} - -func BenchmarkStringShort8(b *testing.B) { - StringHelper(b, 8, shortBase, shortExponent) -} - -func BenchmarkStringShort10(b *testing.B) { - StringHelper(b, 10, shortBase, shortExponent) -} - -func BenchmarkStringShort16(b *testing.B) { - StringHelper(b, 16, shortBase, shortExponent) -} - -func BenchmarkStringMedium2(b *testing.B) { - StringHelper(b, 2, mediumBase, mediumExponent) -} - -func BenchmarkStringMedium8(b *testing.B) { - StringHelper(b, 8, mediumBase, mediumExponent) -} - -func BenchmarkStringMedium10(b *testing.B) { - StringHelper(b, 10, mediumBase, mediumExponent) -} - -func BenchmarkStringMedium16(b *testing.B) { - StringHelper(b, 16, mediumBase, mediumExponent) -} - -func BenchmarkStringLong2(b *testing.B) { - StringHelper(b, 2, longBase, longExponent) -} - -func BenchmarkStringLong8(b *testing.B) { - StringHelper(b, 8, longBase, longExponent) -} - -func BenchmarkStringLong10(b *testing.B) { - StringHelper(b, 10, longBase, longExponent) -} - -func BenchmarkStringLong16(b *testing.B) { - StringHelper(b, 16, longBase, longExponent) -} - -func StringHelper(b *testing.B, base int, xv, yv Word) { - b.StopTimer() - var x, y, z nat - x = x.setWord(xv) - y = y.setWord(yv) - z = z.expNN(x, y, nil) - b.StartTimer() - - for i := 0; i < b.N; i++ { - z.string(lowercaseDigits[0:base]) - } -} - -func TestLeadingZeros(t *testing.T) { - var x Word = _B >> 1 - for i := 0; i <= _W; i++ { - if int(leadingZeros(x)) != i { - t.Errorf("failed at %x: got %d want %d", x, leadingZeros(x), i) - } - x >>= 1 - } -} - -type shiftTest struct { - in nat - shift uint - out nat -} - -var leftShiftTests = []shiftTest{ - {nil, 0, nil}, - {nil, 1, nil}, - {natOne, 0, natOne}, - {natOne, 1, natTwo}, - {nat{1 << (_W - 1)}, 1, nat{0}}, - {nat{1 << (_W - 1), 0}, 1, nat{0, 1}}, -} - -func TestShiftLeft(t *testing.T) { - for i, test := range leftShiftTests { - var z nat - z = z.shl(test.in, test.shift) - for j, d := range test.out { - if j >= len(z) || z[j] != d { - t.Errorf("#%d: got: %v want: %v", i, z, test.out) - break - } - } - } -} - -var rightShiftTests = []shiftTest{ - {nil, 0, nil}, - {nil, 1, nil}, - {natOne, 0, natOne}, - {natOne, 1, nil}, - {natTwo, 1, natOne}, - {nat{0, 1}, 1, nat{1 << (_W - 1)}}, - {nat{2, 1, 1}, 1, nat{1<<(_W-1) + 1, 1 << (_W - 1)}}, -} - -func TestShiftRight(t *testing.T) { - for i, test := range rightShiftTests { - var z nat - z = z.shr(test.in, test.shift) - for j, d := range test.out { - if j >= len(z) || z[j] != d { - t.Errorf("#%d: got: %v want: %v", i, z, test.out) - break - } - } - } -} - -type modWTest struct { - in string - dividend string - out string -} - -var modWTests32 = []modWTest{ - {"23492635982634928349238759823742", "252341", "220170"}, -} - -var modWTests64 = []modWTest{ - {"6527895462947293856291561095690465243862946", "524326975699234", "375066989628668"}, -} - -func runModWTests(t *testing.T, tests []modWTest) { - for i, test := range tests { - in, _ := new(Int).SetString(test.in, 10) - d, _ := new(Int).SetString(test.dividend, 10) - out, _ := new(Int).SetString(test.out, 10) - - r := in.abs.modW(d.abs[0]) - if r != out.abs[0] { - t.Errorf("#%d failed: got %s want %s", i, r, out) - } - } -} - -func TestModW(t *testing.T) { - if _W >= 32 { - runModWTests(t, modWTests32) - } - if _W >= 64 { - runModWTests(t, modWTests64) - } -} - -func TestTrailingZeroBits(t *testing.T) { - var x Word - x-- - for i := 0; i < _W; i++ { - if trailingZeroBits(x) != i { - t.Errorf("Failed at step %d: x: %x got: %d", i, x, trailingZeroBits(x)) - } - x <<= 1 - } -} - -var expNNTests = []struct { - x, y, m string - out string -}{ - {"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"}, - {"0x8000000000000000", "2", "6719", "4944"}, - {"0x8000000000000000", "3", "6719", "5447"}, - {"0x8000000000000000", "1000", "6719", "1603"}, - {"0x8000000000000000", "1000000", "6719", "3199"}, - { - "2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347", - "298472983472983471903246121093472394872319615612417471234712061", - "29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464", - "23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291", - }, -} - -func TestExpNN(t *testing.T) { - for i, test := range expNNTests { - x, _, _ := nat{}.scan(strings.NewReader(test.x), 0) - y, _, _ := nat{}.scan(strings.NewReader(test.y), 0) - out, _, _ := nat{}.scan(strings.NewReader(test.out), 0) - - var m nat - - if len(test.m) > 0 { - m, _, _ = nat{}.scan(strings.NewReader(test.m), 0) - } - - z := nat{}.expNN(x, y, m) - if z.cmp(out) != 0 { - t.Errorf("#%d got %v want %v", i, z, out) - } - } -} diff --git a/libgo/go/big/rat.go b/libgo/go/big/rat.go deleted file mode 100644 index 3a0add3..0000000 --- a/libgo/go/big/rat.go +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file implements multi-precision rational numbers. - -package big - -import ( - "encoding/binary" - "errors" - "fmt" - "strings" -) - -// A Rat represents a quotient a/b of arbitrary precision. -// The zero value for a Rat represents the value 0. -type Rat struct { - a Int - b nat // len(b) == 0 acts like b == 1 -} - -// NewRat creates a new Rat with numerator a and denominator b. -func NewRat(a, b int64) *Rat { - return new(Rat).SetFrac64(a, b) -} - -// SetFrac sets z to a/b and returns z. -func (z *Rat) SetFrac(a, b *Int) *Rat { - z.a.neg = a.neg != b.neg - babs := b.abs - if len(babs) == 0 { - panic("division by zero") - } - if &z.a == b || alias(z.a.abs, babs) { - babs = nat{}.set(babs) // make a copy - } - z.a.abs = z.a.abs.set(a.abs) - z.b = z.b.set(babs) - return z.norm() -} - -// SetFrac64 sets z to a/b and returns z. -func (z *Rat) SetFrac64(a, b int64) *Rat { - z.a.SetInt64(a) - if b == 0 { - panic("division by zero") - } - if b < 0 { - b = -b - z.a.neg = !z.a.neg - } - z.b = z.b.setUint64(uint64(b)) - return z.norm() -} - -// SetInt sets z to x (by making a copy of x) and returns z. -func (z *Rat) SetInt(x *Int) *Rat { - z.a.Set(x) - z.b = z.b.make(0) - return z -} - -// SetInt64 sets z to x and returns z. -func (z *Rat) SetInt64(x int64) *Rat { - z.a.SetInt64(x) - z.b = z.b.make(0) - return z -} - -// Set sets z to x (by making a copy of x) and returns z. -func (z *Rat) Set(x *Rat) *Rat { - if z != x { - z.a.Set(&x.a) - z.b = z.b.set(x.b) - } - return z -} - -// Abs sets z to |x| (the absolute value of x) and returns z. -func (z *Rat) Abs(x *Rat) *Rat { - z.Set(x) - z.a.neg = false - return z -} - -// Neg sets z to -x and returns z. -func (z *Rat) Neg(x *Rat) *Rat { - z.Set(x) - z.a.neg = len(z.a.abs) > 0 && !z.a.neg // 0 has no sign - return z -} - -// Inv sets z to 1/x and returns z. -func (z *Rat) Inv(x *Rat) *Rat { - if len(x.a.abs) == 0 { - panic("division by zero") - } - z.Set(x) - a := z.b - if len(a) == 0 { - a = a.setWord(1) // materialize numerator - } - b := z.a.abs - if b.cmp(natOne) == 0 { - b = b.make(0) // normalize denominator - } - z.a.abs, z.b = a, b // sign doesn't change - return z -} - -// Sign returns: -// -// -1 if x < 0 -// 0 if x == 0 -// +1 if x > 0 -// -func (x *Rat) Sign() int { - return x.a.Sign() -} - -// IsInt returns true if the denominator of x is 1. -func (x *Rat) IsInt() bool { - return len(x.b) == 0 || x.b.cmp(natOne) == 0 -} - -// Num returns the numerator of x; it may be <= 0. -// The result is a reference to x's numerator; it -// may change if a new value is assigned to x. -func (x *Rat) Num() *Int { - return &x.a -} - -// Denom returns the denominator of x; it is always > 0. -// The result is a reference to x's denominator; it -// may change if a new value is assigned to x. -func (x *Rat) Denom() *Int { - if len(x.b) == 0 { - return &Int{abs: nat{1}} - } - return &Int{abs: x.b} -} - -func gcd(x, y nat) nat { - // Euclidean algorithm. - var a, b nat - a = a.set(x) - b = b.set(y) - for len(b) != 0 { - var q, r nat - _, r = q.div(r, a, b) - a = b - b = r - } - return a -} - -func (z *Rat) norm() *Rat { - switch { - case len(z.a.abs) == 0: - // z == 0 - normalize sign and denominator - z.a.neg = false - z.b = z.b.make(0) - case len(z.b) == 0: - // z is normalized int - nothing to do - case z.b.cmp(natOne) == 0: - // z is int - normalize denominator - z.b = z.b.make(0) - default: - if f := gcd(z.a.abs, z.b); f.cmp(natOne) != 0 { - z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f) - z.b, _ = z.b.div(nil, z.b, f) - } - } - return z -} - -// mulDenom sets z to the denominator product x*y (by taking into -// account that 0 values for x or y must be interpreted as 1) and -// returns z. -func mulDenom(z, x, y nat) nat { - switch { - case len(x) == 0: - return z.set(y) - case len(y) == 0: - return z.set(x) - } - return z.mul(x, y) -} - -// scaleDenom computes x*f. -// If f == 0 (zero value of denominator), the result is (a copy of) x. -func scaleDenom(x *Int, f nat) *Int { - var z Int - if len(f) == 0 { - return z.Set(x) - } - z.abs = z.abs.mul(x.abs, f) - z.neg = x.neg - return &z -} - -// Cmp compares x and y and returns: -// -// -1 if x < y -// 0 if x == y -// +1 if x > y -// -func (x *Rat) Cmp(y *Rat) int { - return scaleDenom(&x.a, y.b).Cmp(scaleDenom(&y.a, x.b)) -} - -// Add sets z to the sum x+y and returns z. -func (z *Rat) Add(x, y *Rat) *Rat { - a1 := scaleDenom(&x.a, y.b) - a2 := scaleDenom(&y.a, x.b) - z.a.Add(a1, a2) - z.b = mulDenom(z.b, x.b, y.b) - return z.norm() -} - -// Sub sets z to the difference x-y and returns z. -func (z *Rat) Sub(x, y *Rat) *Rat { - a1 := scaleDenom(&x.a, y.b) - a2 := scaleDenom(&y.a, x.b) - z.a.Sub(a1, a2) - z.b = mulDenom(z.b, x.b, y.b) - return z.norm() -} - -// Mul sets z to the product x*y and returns z. -func (z *Rat) Mul(x, y *Rat) *Rat { - z.a.Mul(&x.a, &y.a) - z.b = mulDenom(z.b, x.b, y.b) - return z.norm() -} - -// Quo sets z to the quotient x/y and returns z. -// If y == 0, a division-by-zero run-time panic occurs. -func (z *Rat) Quo(x, y *Rat) *Rat { - if len(y.a.abs) == 0 { - panic("division by zero") - } - a := scaleDenom(&x.a, y.b) - b := scaleDenom(&y.a, x.b) - z.a.abs = a.abs - z.b = b.abs - z.a.neg = a.neg != b.neg - return z.norm() -} - -func ratTok(ch rune) bool { - return strings.IndexRune("+-/0123456789.eE", ch) >= 0 -} - -// Scan is a support routine for fmt.Scanner. It accepts the formats -// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent. -func (z *Rat) Scan(s fmt.ScanState, ch rune) error { - tok, err := s.Token(true, ratTok) - if err != nil { - return err - } - if strings.IndexRune("efgEFGv", ch) < 0 { - return errors.New("Rat.Scan: invalid verb") - } - if _, ok := z.SetString(string(tok)); !ok { - return errors.New("Rat.Scan: invalid syntax") - } - return nil -} - -// SetString sets z to the value of s and returns z and a boolean indicating -// success. s can be given as a fraction "a/b" or as a floating-point number -// optionally followed by an exponent. If the operation failed, the value of -// z is undefined but the returned value is nil. -func (z *Rat) SetString(s string) (*Rat, bool) { - if len(s) == 0 { - return nil, false - } - - // check for a quotient - sep := strings.Index(s, "/") - if sep >= 0 { - if _, ok := z.a.SetString(s[0:sep], 10); !ok { - return nil, false - } - s = s[sep+1:] - var err error - if z.b, _, err = z.b.scan(strings.NewReader(s), 10); err != nil { - return nil, false - } - return z.norm(), true - } - - // check for a decimal point - sep = strings.Index(s, ".") - // check for an exponent - e := strings.IndexAny(s, "eE") - var exp Int - if e >= 0 { - if e < sep { - // The E must come after the decimal point. - return nil, false - } - if _, ok := exp.SetString(s[e+1:], 10); !ok { - return nil, false - } - s = s[0:e] - } - if sep >= 0 { - s = s[0:sep] + s[sep+1:] - exp.Sub(&exp, NewInt(int64(len(s)-sep))) - } - - if _, ok := z.a.SetString(s, 10); !ok { - return nil, false - } - powTen := nat{}.expNN(natTen, exp.abs, nil) - if exp.neg { - z.b = powTen - z.norm() - } else { - z.a.abs = z.a.abs.mul(z.a.abs, powTen) - z.b = z.b.make(0) - } - - return z, true -} - -// String returns a string representation of z in the form "a/b" (even if b == 1). -func (z *Rat) String() string { - s := "/1" - if len(z.b) != 0 { - s = "/" + z.b.decimalString() - } - return z.a.String() + s -} - -// RatString returns a string representation of z in the form "a/b" if b != 1, -// and in the form "a" if b == 1. -func (z *Rat) RatString() string { - if z.IsInt() { - return z.a.String() - } - return z.String() -} - -// FloatString returns a string representation of z in decimal form with prec -// digits of precision after the decimal point and the last digit rounded. -func (z *Rat) FloatString(prec int) string { - if z.IsInt() { - s := z.a.String() - if prec > 0 { - s += "." + strings.Repeat("0", prec) - } - return s - } - // z.b != 0 - - q, r := nat{}.div(nat{}, z.a.abs, z.b) - - p := natOne - if prec > 0 { - p = nat{}.expNN(natTen, nat{}.setUint64(uint64(prec)), nil) - } - - r = r.mul(r, p) - r, r2 := r.div(nat{}, r, z.b) - - // see if we need to round up - r2 = r2.add(r2, r2) - if z.b.cmp(r2) <= 0 { - r = r.add(r, natOne) - if r.cmp(p) >= 0 { - q = nat{}.add(q, natOne) - r = nat{}.sub(r, p) - } - } - - s := q.decimalString() - if z.a.neg { - s = "-" + s - } - - if prec > 0 { - rs := r.decimalString() - leadingZeros := prec - len(rs) - s += "." + strings.Repeat("0", leadingZeros) + rs - } - - return s -} - -// Gob codec version. Permits backward-compatible changes to the encoding. -const ratGobVersion byte = 1 - -// GobEncode implements the gob.GobEncoder interface. -func (z *Rat) GobEncode() ([]byte, error) { - buf := make([]byte, 1+4+(len(z.a.abs)+len(z.b))*_S) // extra bytes for version and sign bit (1), and numerator length (4) - i := z.b.bytes(buf) - j := z.a.abs.bytes(buf[0:i]) - n := i - j - if int(uint32(n)) != n { - // this should never happen - return nil, errors.New("Rat.GobEncode: numerator too large") - } - binary.BigEndian.PutUint32(buf[j-4:j], uint32(n)) - j -= 1 + 4 - b := ratGobVersion << 1 // make space for sign bit - if z.a.neg { - b |= 1 - } - buf[j] = b - return buf[j:], nil -} - -// GobDecode implements the gob.GobDecoder interface. -func (z *Rat) GobDecode(buf []byte) error { - if len(buf) == 0 { - return errors.New("Rat.GobDecode: no data") - } - b := buf[0] - if b>>1 != ratGobVersion { - return errors.New(fmt.Sprintf("Rat.GobDecode: encoding version %d not supported", b>>1)) - } - const j = 1 + 4 - i := j + binary.BigEndian.Uint32(buf[j-4:j]) - z.a.neg = b&1 != 0 - z.a.abs = z.a.abs.setBytes(buf[j:i]) - z.b = z.b.setBytes(buf[i:]) - return nil -} diff --git a/libgo/go/big/rat_test.go b/libgo/go/big/rat_test.go deleted file mode 100644 index 2443450..0000000 --- a/libgo/go/big/rat_test.go +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package big - -import ( - "bytes" - "fmt" - "gob" - "testing" -) - -func TestZeroRat(t *testing.T) { - var x, y, z Rat - y.SetFrac64(0, 42) - - if x.Cmp(&y) != 0 { - t.Errorf("x and y should be both equal and zero") - } - - if s := x.String(); s != "0/1" { - t.Errorf("got x = %s, want 0/1", s) - } - - if s := x.RatString(); s != "0" { - t.Errorf("got x = %s, want 0", s) - } - - z.Add(&x, &y) - if s := z.RatString(); s != "0" { - t.Errorf("got x+y = %s, want 0", s) - } - - z.Sub(&x, &y) - if s := z.RatString(); s != "0" { - t.Errorf("got x-y = %s, want 0", s) - } - - z.Mul(&x, &y) - if s := z.RatString(); s != "0" { - t.Errorf("got x*y = %s, want 0", s) - } - - // check for division by zero - defer func() { - if s := recover(); s == nil || s.(string) != "division by zero" { - panic(s) - } - }() - z.Quo(&x, &y) -} - -var setStringTests = []struct { - in, out string - ok bool -}{ - {"0", "0", true}, - {"-0", "0", true}, - {"1", "1", true}, - {"-1", "-1", true}, - {"1.", "1", true}, - {"1e0", "1", true}, - {"1.e1", "10", true}, - {in: "1e", ok: false}, - {in: "1.e", ok: false}, - {in: "1e+14e-5", ok: false}, - {in: "1e4.5", ok: false}, - {in: "r", ok: false}, - {in: "a/b", ok: false}, - {in: "a.b", ok: false}, - {"-0.1", "-1/10", true}, - {"-.1", "-1/10", true}, - {"2/4", "1/2", true}, - {".25", "1/4", true}, - {"-1/5", "-1/5", true}, - {"8129567.7690E14", "812956776900000000000", true}, - {"78189e+4", "781890000", true}, - {"553019.8935e+8", "55301989350000", true}, - {"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true}, - {"9877861857500000E-7", "3951144743/4", true}, - {"2169378.417e-3", "2169378417/1000000", true}, - {"884243222337379604041632732738665534", "884243222337379604041632732738665534", true}, - {"53/70893980658822810696", "53/70893980658822810696", true}, - {"106/141787961317645621392", "53/70893980658822810696", true}, - {"204211327800791583.81095", "4084226556015831676219/20000", true}, -} - -func TestRatSetString(t *testing.T) { - for i, test := range setStringTests { - x, ok := new(Rat).SetString(test.in) - - if ok { - if !test.ok { - t.Errorf("#%d SetString(%q) expected failure", i, test.in) - } else if x.RatString() != test.out { - t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out) - } - } else if x != nil { - t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x) - } - } -} - -func TestRatScan(t *testing.T) { - var buf bytes.Buffer - for i, test := range setStringTests { - x := new(Rat) - buf.Reset() - buf.WriteString(test.in) - - _, err := fmt.Fscanf(&buf, "%v", x) - if err == nil != test.ok { - if test.ok { - t.Errorf("#%d error: %s", i, err) - } else { - t.Errorf("#%d expected error", i) - } - continue - } - if err == nil && x.RatString() != test.out { - t.Errorf("#%d got %s want %s", i, x.RatString(), test.out) - } - } -} - -var floatStringTests = []struct { - in string - prec int - out string -}{ - {"0", 0, "0"}, - {"0", 4, "0.0000"}, - {"1", 0, "1"}, - {"1", 2, "1.00"}, - {"-1", 0, "-1"}, - {".25", 2, "0.25"}, - {".25", 1, "0.3"}, - {".25", 3, "0.250"}, - {"-1/3", 3, "-0.333"}, - {"-2/3", 4, "-0.6667"}, - {"0.96", 1, "1.0"}, - {"0.999", 2, "1.00"}, - {"0.9", 0, "1"}, - {".25", -1, "0"}, - {".55", -1, "1"}, -} - -func TestFloatString(t *testing.T) { - for i, test := range floatStringTests { - x, _ := new(Rat).SetString(test.in) - - if x.FloatString(test.prec) != test.out { - t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out) - } - } -} - -func TestRatSign(t *testing.T) { - zero := NewRat(0, 1) - for _, a := range setStringTests { - x, ok := new(Rat).SetString(a.in) - if !ok { - continue - } - s := x.Sign() - e := x.Cmp(zero) - if s != e { - t.Errorf("got %d; want %d for z = %v", s, e, &x) - } - } -} - -var ratCmpTests = []struct { - rat1, rat2 string - out int -}{ - {"0", "0/1", 0}, - {"1/1", "1", 0}, - {"-1", "-2/2", 0}, - {"1", "0", 1}, - {"0/1", "1/1", -1}, - {"-5/1434770811533343057144", "-5/1434770811533343057145", -1}, - {"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1}, - {"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1}, - {"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0}, -} - -func TestRatCmp(t *testing.T) { - for i, test := range ratCmpTests { - x, _ := new(Rat).SetString(test.rat1) - y, _ := new(Rat).SetString(test.rat2) - - out := x.Cmp(y) - if out != test.out { - t.Errorf("#%d got out = %v; want %v", i, out, test.out) - } - } -} - -func TestIsInt(t *testing.T) { - one := NewInt(1) - for _, a := range setStringTests { - x, ok := new(Rat).SetString(a.in) - if !ok { - continue - } - i := x.IsInt() - e := x.Denom().Cmp(one) == 0 - if i != e { - t.Errorf("got IsInt(%v) == %v; want %v", x, i, e) - } - } -} - -func TestRatAbs(t *testing.T) { - zero := new(Rat) - for _, a := range setStringTests { - x, ok := new(Rat).SetString(a.in) - if !ok { - continue - } - e := new(Rat).Set(x) - if e.Cmp(zero) < 0 { - e.Sub(zero, e) - } - z := new(Rat).Abs(x) - if z.Cmp(e) != 0 { - t.Errorf("got Abs(%v) = %v; want %v", x, z, e) - } - } -} - -func TestRatNeg(t *testing.T) { - zero := new(Rat) - for _, a := range setStringTests { - x, ok := new(Rat).SetString(a.in) - if !ok { - continue - } - e := new(Rat).Sub(zero, x) - z := new(Rat).Neg(x) - if z.Cmp(e) != 0 { - t.Errorf("got Neg(%v) = %v; want %v", x, z, e) - } - } -} - -func TestRatInv(t *testing.T) { - zero := new(Rat) - for _, a := range setStringTests { - x, ok := new(Rat).SetString(a.in) - if !ok { - continue - } - if x.Cmp(zero) == 0 { - continue // avoid division by zero - } - e := new(Rat).SetFrac(x.Denom(), x.Num()) - z := new(Rat).Inv(x) - if z.Cmp(e) != 0 { - t.Errorf("got Inv(%v) = %v; want %v", x, z, e) - } - } -} - -type ratBinFun func(z, x, y *Rat) *Rat -type ratBinArg struct { - x, y, z string -} - -func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) { - x, _ := new(Rat).SetString(a.x) - y, _ := new(Rat).SetString(a.y) - z, _ := new(Rat).SetString(a.z) - out := f(new(Rat), x, y) - - if out.Cmp(z) != 0 { - t.Errorf("%s #%d got %s want %s", name, i, out, z) - } -} - -var ratBinTests = []struct { - x, y string - sum, prod string -}{ - {"0", "0", "0", "0"}, - {"0", "1", "1", "0"}, - {"-1", "0", "-1", "0"}, - {"-1", "1", "0", "-1"}, - {"1", "1", "2", "1"}, - {"1/2", "1/2", "1", "1/4"}, - {"1/4", "1/3", "7/12", "1/12"}, - {"2/5", "-14/3", "-64/15", "-28/15"}, - {"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"}, - {"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"}, - {"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"}, - {"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"}, - {"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"}, - {"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"}, - {"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"}, - {"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"}, - {"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"}, - {"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"}, -} - -func TestRatBin(t *testing.T) { - for i, test := range ratBinTests { - arg := ratBinArg{test.x, test.y, test.sum} - testRatBin(t, i, "Add", (*Rat).Add, arg) - - arg = ratBinArg{test.y, test.x, test.sum} - testRatBin(t, i, "Add symmetric", (*Rat).Add, arg) - - arg = ratBinArg{test.sum, test.x, test.y} - testRatBin(t, i, "Sub", (*Rat).Sub, arg) - - arg = ratBinArg{test.sum, test.y, test.x} - testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg) - - arg = ratBinArg{test.x, test.y, test.prod} - testRatBin(t, i, "Mul", (*Rat).Mul, arg) - - arg = ratBinArg{test.y, test.x, test.prod} - testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg) - - if test.x != "0" { - arg = ratBinArg{test.prod, test.x, test.y} - testRatBin(t, i, "Quo", (*Rat).Quo, arg) - } - - if test.y != "0" { - arg = ratBinArg{test.prod, test.y, test.x} - testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg) - } - } -} - -func TestIssue820(t *testing.T) { - x := NewRat(3, 1) - y := NewRat(2, 1) - z := y.Quo(x, y) - q := NewRat(3, 2) - if z.Cmp(q) != 0 { - t.Errorf("got %s want %s", z, q) - } - - y = NewRat(3, 1) - x = NewRat(2, 1) - z = y.Quo(x, y) - q = NewRat(2, 3) - if z.Cmp(q) != 0 { - t.Errorf("got %s want %s", z, q) - } - - x = NewRat(3, 1) - z = x.Quo(x, x) - q = NewRat(3, 3) - if z.Cmp(q) != 0 { - t.Errorf("got %s want %s", z, q) - } -} - -var setFrac64Tests = []struct { - a, b int64 - out string -}{ - {0, 1, "0"}, - {0, -1, "0"}, - {1, 1, "1"}, - {-1, 1, "-1"}, - {1, -1, "-1"}, - {-1, -1, "1"}, - {-9223372036854775808, -9223372036854775808, "1"}, -} - -func TestRatSetFrac64Rat(t *testing.T) { - for i, test := range setFrac64Tests { - x := new(Rat).SetFrac64(test.a, test.b) - if x.RatString() != test.out { - t.Errorf("#%d got %s want %s", i, x.RatString(), test.out) - } - } -} - -func TestRatGobEncoding(t *testing.T) { - var medium bytes.Buffer - enc := gob.NewEncoder(&medium) - dec := gob.NewDecoder(&medium) - for i, test := range gobEncodingTests { - for j := 0; j < 4; j++ { - medium.Reset() // empty buffer for each test case (in case of failures) - stest := test - if j&1 != 0 { - // negative numbers - stest = "-" + test - } - if j%2 != 0 { - // fractions - stest = stest + "." + test - } - var tx Rat - tx.SetString(stest) - if err := enc.Encode(&tx); err != nil { - t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err) - } - var rx Rat - if err := dec.Decode(&rx); err != nil { - t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err) - } - if rx.Cmp(&tx) != 0 { - t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx) - } - } - } -} - -func TestIssue2379(t *testing.T) { - // 1) no aliasing - q := NewRat(3, 2) - x := new(Rat) - x.SetFrac(NewInt(3), NewInt(2)) - if x.Cmp(q) != 0 { - t.Errorf("1) got %s want %s", x, q) - } - - // 2) aliasing of numerator - x = NewRat(2, 3) - x.SetFrac(NewInt(3), x.Num()) - if x.Cmp(q) != 0 { - t.Errorf("2) got %s want %s", x, q) - } - - // 3) aliasing of denominator - x = NewRat(2, 3) - x.SetFrac(x.Denom(), NewInt(2)) - if x.Cmp(q) != 0 { - t.Errorf("3) got %s want %s", x, q) - } - - // 4) aliasing of numerator and denominator - x = NewRat(2, 3) - x.SetFrac(x.Denom(), x.Num()) - if x.Cmp(q) != 0 { - t.Errorf("4) got %s want %s", x, q) - } - - // 5) numerator and denominator are the same - q = NewRat(1, 1) - x = new(Rat) - n := NewInt(7) - x.SetFrac(n, n) - if x.Cmp(q) != 0 { - t.Errorf("5) got %s want %s", x, q) - } -} diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go index f4ed91b..61e338b 100644 --- a/libgo/go/bufio/bufio.go +++ b/libgo/go/bufio/bufio.go @@ -11,7 +11,7 @@ import ( "bytes" "io" "strconv" - "utf8" + "unicode/utf8" ) const ( @@ -135,7 +135,7 @@ func (b *Reader) Peek(n int) ([]byte, error) { // It returns the number of bytes read into p. // It calls Read at most once on the underlying Reader, // hence n may be less than len(p). -// At EOF, the count will be zero and err will be os.EOF. +// At EOF, the count will be zero and err will be io.EOF. func (b *Reader) Read(p []byte) (n int, err error) { n = len(p) if n == 0 { @@ -246,7 +246,7 @@ func (b *Reader) Buffered() int { return b.w - b.r } // returning a slice pointing at the bytes in the buffer. // The bytes stop being valid at the next read call. // If ReadSlice encounters an error before finding a delimiter, -// it returns all the data in the buffer and the error itself (often os.EOF). +// it returns all the data in the buffer and the error itself (often io.EOF). // ReadSlice fails with error ErrBufferFull if the buffer fills without a delim. // Because the data returned from ReadSlice will be overwritten // by the next I/O operation, most clients should use @@ -312,6 +312,9 @@ func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) { } if len(line) == 0 { + if err != nil { + line = nil + } return } err = nil @@ -329,7 +332,7 @@ func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) { // ReadBytes reads until the first occurrence of delim in the input, // returning a slice containing the data up to and including the delimiter. // If ReadBytes encounters an error before finding a delimiter, -// it returns the data read before the error and the error itself (often os.EOF). +// it returns the data read before the error and the error itself (often io.EOF). // ReadBytes returns err != nil if and only if the returned data does not end in // delim. func (b *Reader) ReadBytes(delim byte) (line []byte, err error) { @@ -376,7 +379,7 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err error) { // ReadString reads until the first occurrence of delim in the input, // returning a string containing the data up to and including the delimiter. // If ReadString encounters an error before finding a delimiter, -// it returns the data read before the error and the error itself (often os.EOF). +// it returns the data read before the error and the error itself (often io.EOF). // ReadString returns err != nil if and only if the returned data does not end in // delim. func (b *Reader) ReadString(delim byte) (line string, err error) { diff --git a/libgo/go/bufio/bufio_test.go b/libgo/go/bufio/bufio_test.go index 0285dee..1f89395 100644 --- a/libgo/go/bufio/bufio_test.go +++ b/libgo/go/bufio/bufio_test.go @@ -14,7 +14,7 @@ import ( "strings" "testing" "testing/iotest" - "utf8" + "unicode/utf8" ) // Reads from a reader and rot13s the result. @@ -698,6 +698,17 @@ func TestLinesAfterRead(t *testing.T) { } } +func TestReadLineNonNilLineOrError(t *testing.T) { + r := NewReader(strings.NewReader("line 1\n")) + for i := 0; i < 2; i++ { + l, _, err := r.ReadLine() + if l != nil && err != nil { + t.Fatalf("on line %d/2; ReadLine=%#v, %v; want non-nil line or Error, but not both", + i+1, l, err) + } + } +} + type readLineResult struct { line []byte isPrefix bool diff --git a/libgo/go/builtin/builtin.go b/libgo/go/builtin/builtin.go index 07acce4..5a7aaf3 100644 --- a/libgo/go/builtin/builtin.go +++ b/libgo/go/builtin/builtin.go @@ -3,13 +3,89 @@ // license that can be found in the LICENSE file. /* - Package builtin provides documentation for Go's built-in functions. - The functions documented here are not actually in package builtin + Package builtin provides documentation for Go's predeclared identifiers. + The items documented here are not actually in package builtin but their descriptions here allow godoc to present documentation - for the language's special functions. + for the language's special identifiers. */ package builtin +// bool is the set of boolean values, true and false. +type bool bool + +// uint8 is the set of all unsigned 8-bit integers. +// Range: 0 through 255. +type uint8 uint8 + +// uint16 is the set of all unsigned 16-bit integers. +// Range: 0 through 65535. +type uint16 uint16 + +// uint32 is the set of all unsigned 32-bit integers. +// Range: 0 through 4294967295. +type uint32 uint32 + +// uint64 is the set of all unsigned 64-bit integers. +// Range: 0 through 18446744073709551615. +type uint64 uint64 + +// int8 is the set of all signed 8-bit integers. +// Range: -128 through 127. +type int8 int8 + +// int16 is the set of all signed 16-bit integers. +// Range: -32768 through 32767. +type int16 int16 + +// int32 is the set of all signed 32-bit integers. +// Range: -2147483648 through 2147483647. +type int32 int32 + +// int64 is the set of all signed 64-bit integers. +// Range: -9223372036854775808 through 9223372036854775807. +type int64 int64 + +// float32 is the set of all IEEE-754 32-bit floating-point numbers. +type float32 float32 + +// float64 is the set of all IEEE-754 64-bit floating-point numbers. +type float64 float64 + +// complex64 is the set of all complex numbers with float32 real and +// imaginary parts. +type complex64 complex64 + +// complex128 is the set of all complex numbers with float64 real and +// imaginary parts. +type complex128 complex128 + +// string is the set of all strings of 8-bit bytes, conventionally but not +// necessarily representing UTF-8-encoded text. A string may be empty, but +// not nil. Values of string type are immutable. +type string string + +// int is a signed integer type that is at least 32 bits in size. It is a +// distinct type, however, and not an alias for, say, int32. +type int int + +// uint is an unsigned integer type that is at least 32 bits in size. It is a +// distinct type, however, and not an alias for, say, uint32. +type uint uint + +// uintptr is an integer type that is large enough to hold the bit pattern of +// any pointer. +type uintptr uintptr + +// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is +// used, by convention, to distinguish byte values from 8-bit unsigned +// integer values. +type byte byte + +// rune is an alias for int and is equivalent to int in all ways. It is +// used, by convention, to distinguish character values from integer values. +// In a future version of Go, it will change to an alias of int32. +type rune rune + // Type is here for the purposes of documentation only. It is a stand-in // for any Go type, but represents the same type for any given function // invocation. @@ -21,11 +97,11 @@ type IntegerType int // FloatType is here for the purposes of documentation only. It is a stand-in // for either float type: float32 or float64. -type FloatType int +type FloatType float32 // ComplexType is here for the purposes of documentation only. It is a // stand-in for either complex type: complex64 or complex128. -type ComplexType int +type ComplexType complex64 // The append built-in function appends elements to the end of a slice. If // it has sufficient capacity, the destination is resliced to accommodate the @@ -133,3 +209,9 @@ func panic(v interface{}) // nil. Thus the return value from recover reports whether the goroutine is // panicking. func recover() interface{} + +// The error built-in interface type is the conventional interface for +// representing an error condition, with the nil value representing no error. +type error interface { + Error() string +} diff --git a/libgo/go/bytes/buffer.go b/libgo/go/bytes/buffer.go index fbfd621..e66ac02 100644 --- a/libgo/go/bytes/buffer.go +++ b/libgo/go/bytes/buffer.go @@ -9,7 +9,7 @@ package bytes import ( "errors" "io" - "utf8" + "unicode/utf8" ) // A Buffer is a variable-sized buffer of bytes with Read and Write methods. @@ -117,7 +117,7 @@ const MinRead = 512 // ReadFrom reads data from r until EOF and appends it to the buffer. // The return value n is the number of bytes read. -// Any error except os.EOF encountered during the read +// Any error except io.EOF encountered during the read // is also returned. func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) { b.lastRead = opInvalid @@ -200,7 +200,7 @@ func (b *Buffer) WriteRune(r rune) (n int, err error) { // Read reads the next len(p) bytes from the buffer or until the buffer // is drained. The return value n is the number of bytes read. If the -// buffer has no data to return, err is os.EOF even if len(p) is zero; +// buffer has no data to return, err is io.EOF even if len(p) is zero; // otherwise it is nil. func (b *Buffer) Read(p []byte) (n int, err error) { b.lastRead = opInvalid @@ -236,7 +236,7 @@ func (b *Buffer) Next(n int) []byte { } // ReadByte reads and returns the next byte from the buffer. -// If no byte is available, it returns error os.EOF. +// If no byte is available, it returns error io.EOF. func (b *Buffer) ReadByte() (c byte, err error) { b.lastRead = opInvalid if b.off >= len(b.buf) { @@ -252,7 +252,7 @@ func (b *Buffer) ReadByte() (c byte, err error) { // ReadRune reads and returns the next UTF-8-encoded // Unicode code point from the buffer. -// If no bytes are available, the error returned is os.EOF. +// If no bytes are available, the error returned is io.EOF. // If the bytes are an erroneous UTF-8 encoding, it // consumes one byte and returns U+FFFD, 1. func (b *Buffer) ReadRune() (r rune, size int, err error) { @@ -307,7 +307,7 @@ func (b *Buffer) UnreadByte() error { // ReadBytes reads until the first occurrence of delim in the input, // returning a slice containing the data up to and including the delimiter. // If ReadBytes encounters an error before finding a delimiter, -// it returns the data read before the error and the error itself (often os.EOF). +// it returns the data read before the error and the error itself (often io.EOF). // ReadBytes returns err != nil if and only if the returned data does not end in // delim. func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) { @@ -326,7 +326,7 @@ func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) { // ReadString reads until the first occurrence of delim in the input, // returning a string containing the data up to and including the delimiter. // If ReadString encounters an error before finding a delimiter, -// it returns the data read before the error and the error itself (often os.EOF). +// it returns the data read before the error and the error itself (often io.EOF). // ReadString returns err != nil if and only if the returned data does not end // in delim. func (b *Buffer) ReadString(delim byte) (line string, err error) { diff --git a/libgo/go/bytes/buffer_test.go b/libgo/go/bytes/buffer_test.go index c271b48..5235970 100644 --- a/libgo/go/bytes/buffer_test.go +++ b/libgo/go/bytes/buffer_test.go @@ -7,9 +7,9 @@ package bytes_test import ( . "bytes" "io" - "rand" + "math/rand" "testing" - "utf8" + "unicode/utf8" ) const N = 10000 // make this bigger for a larger (and slower) test diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go index ac8320f..9bfd88f 100644 --- a/libgo/go/bytes/bytes.go +++ b/libgo/go/bytes/bytes.go @@ -8,7 +8,7 @@ package bytes import ( "unicode" - "utf8" + "unicode/utf8" ) // Compare returns an integer comparing the two byte arrays lexicographically. @@ -88,6 +88,11 @@ func Count(s, sep []byte) int { return n } +// Contains returns whether subslice is within b. +func Contains(b, subslice []byte) bool { + return Index(b, subslice) != -1 +} + // Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. func Index(s, sep []byte) int { n := len(sep) diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go index 62f258d..9256b18 100644 --- a/libgo/go/bytes/bytes_test.go +++ b/libgo/go/bytes/bytes_test.go @@ -9,7 +9,7 @@ import ( "reflect" "testing" "unicode" - "utf8" + "unicode/utf8" ) func eq(a, b []string) bool { diff --git a/libgo/go/cmath/abs.go b/libgo/go/cmath/abs.go deleted file mode 100644 index f3199ca..0000000 --- a/libgo/go/cmath/abs.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package cmath provides basic constants and mathematical functions for -// complex numbers. -package cmath - -import "math" - -// Abs returns the absolute value (also called the modulus) of x. -func Abs(x complex128) float64 { return math.Hypot(real(x), imag(x)) } diff --git a/libgo/go/cmath/asin.go b/libgo/go/cmath/asin.go deleted file mode 100644 index 01ce80a..0000000 --- a/libgo/go/cmath/asin.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// The original C code, the long comment, and the constants -// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. -// The go code is a simplified version of the original C. -// -// Cephes Math Library Release 2.8: June, 2000 -// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -// -// The readme file at http://netlib.sandia.gov/cephes/ says: -// Some software in this archive may be from the book _Methods and -// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster -// International, 1989) or from the Cephes Mathematical Library, a -// commercial product. In either event, it is copyrighted by the author. -// What you see here may be used freely but it comes with no support or -// guarantee. -// -// The two known misprints in the book are repaired here in the -// source listings for the gamma function and the incomplete beta -// integral. -// -// Stephen L. Moshier -// moshier@na-net.ornl.gov - -// Complex circular arc sine -// -// DESCRIPTION: -// -// Inverse complex sine: -// 2 -// w = -i clog( iz + csqrt( 1 - z ) ). -// -// casin(z) = -i casinh(iz) -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 10100 2.1e-15 3.4e-16 -// IEEE -10,+10 30000 2.2e-14 2.7e-15 -// Larger relative error can be observed for z near zero. -// Also tested by csin(casin(z)) = z. - -// Asin returns the inverse sine of x. -func Asin(x complex128) complex128 { - if imag(x) == 0 { - if math.Abs(real(x)) > 1 { - return complex(math.Pi/2, 0) // DOMAIN error - } - return complex(math.Asin(real(x)), 0) - } - ct := complex(-imag(x), real(x)) // i * x - xx := x * x - x1 := complex(1-real(xx), -imag(xx)) // 1 - x*x - x2 := Sqrt(x1) // x2 = sqrt(1 - x*x) - w := Log(ct + x2) - return complex(imag(w), -real(w)) // -i * w -} - -// Asinh returns the inverse hyperbolic sine of x. -func Asinh(x complex128) complex128 { - // TODO check range - if imag(x) == 0 { - if math.Abs(real(x)) > 1 { - return complex(math.Pi/2, 0) // DOMAIN error - } - return complex(math.Asinh(real(x)), 0) - } - xx := x * x - x1 := complex(1+real(xx), imag(xx)) // 1 + x*x - return Log(x + Sqrt(x1)) // log(x + sqrt(1 + x*x)) -} - -// Complex circular arc cosine -// -// DESCRIPTION: -// -// w = arccos z = PI/2 - arcsin z. -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 5200 1.6e-15 2.8e-16 -// IEEE -10,+10 30000 1.8e-14 2.2e-15 - -// Acos returns the inverse cosine of x. -func Acos(x complex128) complex128 { - w := Asin(x) - return complex(math.Pi/2-real(w), -imag(w)) -} - -// Acosh returns the inverse hyperbolic cosine of x. -func Acosh(x complex128) complex128 { - w := Acos(x) - if imag(w) <= 0 { - return complex(-imag(w), real(w)) // i * w - } - return complex(imag(w), -real(w)) // -i * w -} - -// Complex circular arc tangent -// -// DESCRIPTION: -// -// If -// z = x + iy, -// -// then -// 1 ( 2x ) -// Re w = - arctan(-----------) + k PI -// 2 ( 2 2) -// (1 - x - y ) -// -// ( 2 2) -// 1 (x + (y+1) ) -// Im w = - log(------------) -// 4 ( 2 2) -// (x + (y-1) ) -// -// Where k is an arbitrary integer. -// -// catan(z) = -i catanh(iz). -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 5900 1.3e-16 7.8e-18 -// IEEE -10,+10 30000 2.3e-15 8.5e-17 -// The check catan( ctan(z) ) = z, with |x| and |y| < PI/2, -// had peak relative error 1.5e-16, rms relative error -// 2.9e-17. See also clog(). - -// Atan returns the inverse tangent of x. -func Atan(x complex128) complex128 { - if real(x) == 0 && imag(x) > 1 { - return NaN() - } - - x2 := real(x) * real(x) - a := 1 - x2 - imag(x)*imag(x) - if a == 0 { - return NaN() - } - t := 0.5 * math.Atan2(2*real(x), a) - w := reducePi(t) - - t = imag(x) - 1 - b := x2 + t*t - if b == 0 { - return NaN() - } - t = imag(x) + 1 - c := (x2 + t*t) / b - return complex(w, 0.25*math.Log(c)) -} - -// Atanh returns the inverse hyperbolic tangent of x. -func Atanh(x complex128) complex128 { - z := complex(-imag(x), real(x)) // z = i * x - z = Atan(z) - return complex(imag(z), -real(z)) // z = -i * z -} diff --git a/libgo/go/cmath/cmath_test.go b/libgo/go/cmath/cmath_test.go deleted file mode 100644 index 6a595b0..0000000 --- a/libgo/go/cmath/cmath_test.go +++ /dev/null @@ -1,853 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import ( - "math" - "testing" -) - -var vc26 = []complex128{ - (4.97901192488367350108546816 + 7.73887247457810456552351752i), - (7.73887247457810456552351752 - 0.27688005719200159404635997i), - (-0.27688005719200159404635997 - 5.01060361827107492160848778i), - (-5.01060361827107492160848778 + 9.63629370719841737980004837i), - (9.63629370719841737980004837 + 2.92637723924396464525443662i), - (2.92637723924396464525443662 + 5.22908343145930665230025625i), - (5.22908343145930665230025625 + 2.72793991043601025126008608i), - (2.72793991043601025126008608 + 1.82530809168085506044576505i), - (1.82530809168085506044576505 - 8.68592476857560136238589621i), - (-8.68592476857560136238589621 + 4.97901192488367350108546816i), -} -var vc = []complex128{ - (4.9790119248836735e+00 + 7.7388724745781045e+00i), - (7.7388724745781045e+00 - 2.7688005719200159e-01i), - (-2.7688005719200159e-01 - 5.0106036182710749e+00i), - (-5.0106036182710749e+00 + 9.6362937071984173e+00i), - (9.6362937071984173e+00 + 2.9263772392439646e+00i), - (2.9263772392439646e+00 + 5.2290834314593066e+00i), - (5.2290834314593066e+00 + 2.7279399104360102e+00i), - (2.7279399104360102e+00 + 1.8253080916808550e+00i), - (1.8253080916808550e+00 - 8.6859247685756013e+00i), - (-8.6859247685756013e+00 + 4.9790119248836735e+00i), -} - -// The expected results below were computed by the high precision calculators -// at http://keisan.casio.com/. More exact input values (array vc[], above) -// were obtained by printing them with "%.26f". The answers were calculated -// to 26 digits (by using the "Digit number" drop-down control of each -// calculator). - -var abs = []float64{ - 9.2022120669932650313380972e+00, - 7.7438239742296106616261394e+00, - 5.0182478202557746902556648e+00, - 1.0861137372799545160704002e+01, - 1.0070841084922199607011905e+01, - 5.9922447613166942183705192e+00, - 5.8978784056736762299945176e+00, - 3.2822866700678709020367184e+00, - 8.8756430028990417290744307e+00, - 1.0011785496777731986390856e+01, -} - -var acos = []complex128{ - (1.0017679804707456328694569 - 2.9138232718554953784519807i), - (0.03606427612041407369636057 + 2.7358584434576260925091256i), - (1.6249365462333796703711823 + 2.3159537454335901187730929i), - (2.0485650849650740120660391 - 3.0795576791204117911123886i), - (0.29621132089073067282488147 - 3.0007392508200622519398814i), - (1.0664555914934156601503632 - 2.4872865024796011364747111i), - (0.48681307452231387690013905 - 2.463655912283054555225301i), - (0.6116977071277574248407752 - 1.8734458851737055262693056i), - (1.3649311280370181331184214 + 2.8793528632328795424123832i), - (2.6189310485682988308904501 - 2.9956543302898767795858704i), -} -var acosh = []complex128{ - (2.9138232718554953784519807 + 1.0017679804707456328694569i), - (2.7358584434576260925091256 - 0.03606427612041407369636057i), - (2.3159537454335901187730929 - 1.6249365462333796703711823i), - (3.0795576791204117911123886 + 2.0485650849650740120660391i), - (3.0007392508200622519398814 + 0.29621132089073067282488147i), - (2.4872865024796011364747111 + 1.0664555914934156601503632i), - (2.463655912283054555225301 + 0.48681307452231387690013905i), - (1.8734458851737055262693056 + 0.6116977071277574248407752i), - (2.8793528632328795424123832 - 1.3649311280370181331184214i), - (2.9956543302898767795858704 + 2.6189310485682988308904501i), -} -var asin = []complex128{ - (0.56902834632415098636186476 + 2.9138232718554953784519807i), - (1.5347320506744825455349611 - 2.7358584434576260925091256i), - (-0.054140219438483051139860579 - 2.3159537454335901187730929i), - (-0.47776875817017739283471738 + 3.0795576791204117911123886i), - (1.2745850059041659464064402 + 3.0007392508200622519398814i), - (0.50434073530148095908095852 + 2.4872865024796011364747111i), - (1.0839832522725827423311826 + 2.463655912283054555225301i), - (0.9590986196671391943905465 + 1.8734458851737055262693056i), - (0.20586519875787848611290031 - 2.8793528632328795424123832i), - (-1.0481347217734022116591284 + 2.9956543302898767795858704i), -} -var asinh = []complex128{ - (2.9113760469415295679342185 + 0.99639459545704326759805893i), - (2.7441755423994259061579029 - 0.035468308789000500601119392i), - (-2.2962136462520690506126678 - 1.5144663565690151885726707i), - (-3.0771233459295725965402455 + 1.0895577967194013849422294i), - (3.0048366100923647417557027 + 0.29346979169819220036454168i), - (2.4800059370795363157364643 + 1.0545868606049165710424232i), - (2.4718773838309585611141821 + 0.47502344364250803363708842i), - (1.8910743588080159144378396 + 0.56882925572563602341139174i), - (2.8735426423367341878069406 - 1.362376149648891420997548i), - (-2.9981750586172477217567878 + 0.5183571985225367505624207i), -} -var atan = []complex128{ - (1.5115747079332741358607654 + 0.091324403603954494382276776i), - (1.4424504323482602560806727 - 0.0045416132642803911503770933i), - (-1.5593488703630532674484026 - 0.20163295409248362456446431i), - (-1.5280619472445889867794105 + 0.081721556230672003746956324i), - (1.4759909163240799678221039 + 0.028602969320691644358773586i), - (1.4877353772046548932715555 + 0.14566877153207281663773599i), - (1.4206983927779191889826 + 0.076830486127880702249439993i), - (1.3162236060498933364869556 + 0.16031313000467530644933363i), - (1.5473450684303703578810093 - 0.11064907507939082484935782i), - (-1.4841462340185253987375812 + 0.049341850305024399493142411i), -} -var atanh = []complex128{ - (0.058375027938968509064640438 + 1.4793488495105334458167782i), - (0.12977343497790381229915667 - 1.5661009410463561327262499i), - (-0.010576456067347252072200088 - 1.3743698658402284549750563i), - (-0.042218595678688358882784918 + 1.4891433968166405606692604i), - (0.095218997991316722061828397 + 1.5416884098777110330499698i), - (0.079965459366890323857556487 + 1.4252510353873192700350435i), - (0.15051245471980726221708301 + 1.4907432533016303804884461i), - (0.25082072933993987714470373 + 1.392057665392187516442986i), - (0.022896108815797135846276662 - 1.4609224989282864208963021i), - (-0.08665624101841876130537396 + 1.5207902036935093480142159i), -} -var conj = []complex128{ - (4.9790119248836735e+00 - 7.7388724745781045e+00i), - (7.7388724745781045e+00 + 2.7688005719200159e-01i), - (-2.7688005719200159e-01 + 5.0106036182710749e+00i), - (-5.0106036182710749e+00 - 9.6362937071984173e+00i), - (9.6362937071984173e+00 - 2.9263772392439646e+00i), - (2.9263772392439646e+00 - 5.2290834314593066e+00i), - (5.2290834314593066e+00 - 2.7279399104360102e+00i), - (2.7279399104360102e+00 - 1.8253080916808550e+00i), - (1.8253080916808550e+00 + 8.6859247685756013e+00i), - (-8.6859247685756013e+00 - 4.9790119248836735e+00i), -} -var cos = []complex128{ - (3.024540920601483938336569e+02 + 1.1073797572517071650045357e+03i), - (1.192858682649064973252758e-01 + 2.7857554122333065540970207e-01i), - (7.2144394304528306603857962e+01 - 2.0500129667076044169954205e+01i), - (2.24921952538403984190541e+03 - 7.317363745602773587049329e+03i), - (-9.148222970032421760015498e+00 + 1.953124661113563541862227e+00i), - (-9.116081175857732248227078e+01 - 1.992669213569952232487371e+01i), - (3.795639179042704640002918e+00 + 6.623513350981458399309662e+00i), - (-2.9144840732498869560679084e+00 - 1.214620271628002917638748e+00i), - (-7.45123482501299743872481e+02 + 2.8641692314488080814066734e+03i), - (-5.371977967039319076416747e+01 + 4.893348341339375830564624e+01i), -} -var cosh = []complex128{ - (8.34638383523018249366948e+00 + 7.2181057886425846415112064e+01i), - (1.10421967379919366952251e+03 - 3.1379638689277575379469861e+02i), - (3.051485206773701584738512e-01 - 2.6805384730105297848044485e-01i), - (-7.33294728684187933370938e+01 + 1.574445942284918251038144e+01i), - (-7.478643293945957535757355e+03 + 1.6348382209913353929473321e+03i), - (4.622316522966235701630926e+00 - 8.088695185566375256093098e+00i), - (-8.544333183278877406197712e+01 + 3.7505836120128166455231717e+01i), - (-1.934457815021493925115198e+00 + 7.3725859611767228178358673e+00i), - (-2.352958770061749348353548e+00 - 2.034982010440878358915409e+00i), - (7.79756457532134748165069e+02 + 2.8549350716819176560377717e+03i), -} -var exp = []complex128{ - (1.669197736864670815125146e+01 + 1.4436895109507663689174096e+02i), - (2.2084389286252583447276212e+03 - 6.2759289284909211238261917e+02i), - (2.227538273122775173434327e-01 + 7.2468284028334191250470034e-01i), - (-6.5182985958153548997881627e-03 - 1.39965837915193860879044e-03i), - (-1.4957286524084015746110777e+04 + 3.269676455931135688988042e+03i), - (9.218158701983105935659273e+00 - 1.6223985291084956009304582e+01i), - (-1.7088175716853040841444505e+02 + 7.501382609870410713795546e+01i), - (-3.852461315830959613132505e+00 + 1.4808420423156073221970892e+01i), - (-4.586775503301407379786695e+00 - 4.178501081246873415144744e+00i), - (4.451337963005453491095747e-05 - 1.62977574205442915935263e-04i), -} -var log = []complex128{ - (2.2194438972179194425697051e+00 + 9.9909115046919291062461269e-01i), - (2.0468956191154167256337289e+00 - 3.5762575021856971295156489e-02i), - (1.6130808329853860438751244e+00 - 1.6259990074019058442232221e+00i), - (2.3851910394823008710032651e+00 + 2.0502936359659111755031062e+00i), - (2.3096442270679923004800651e+00 + 2.9483213155446756211881774e-01i), - (1.7904660933974656106951860e+00 + 1.0605860367252556281902109e+00i), - (1.7745926939841751666177512e+00 + 4.8084556083358307819310911e-01i), - (1.1885403350045342425648780e+00 + 5.8969634164776659423195222e-01i), - (2.1833107837679082586772505e+00 - 1.3636647724582455028314573e+00i), - (2.3037629487273259170991671e+00 + 2.6210913895386013290915234e+00i), -} -var log10 = []complex128{ - (9.6389223745559042474184943e-01 + 4.338997735671419492599631e-01i), - (8.8895547241376579493490892e-01 - 1.5531488990643548254864806e-02i), - (7.0055210462945412305244578e-01 - 7.0616239649481243222248404e-01i), - (1.0358753067322445311676952e+00 + 8.9043121238134980156490909e-01i), - (1.003065742975330237172029e+00 + 1.2804396782187887479857811e-01i), - (7.7758954439739162532085157e-01 + 4.6060666333341810869055108e-01i), - (7.7069581462315327037689152e-01 + 2.0882857371769952195512475e-01i), - (5.1617650901191156135137239e-01 + 2.5610186717615977620363299e-01i), - (9.4819982567026639742663212e-01 - 5.9223208584446952284914289e-01i), - (1.0005115362454417135973429e+00 + 1.1383255270407412817250921e+00i), -} - -type ff struct { - r, theta float64 -} - -var polar = []ff{ - {9.2022120669932650313380972e+00, 9.9909115046919291062461269e-01}, - {7.7438239742296106616261394e+00, -3.5762575021856971295156489e-02}, - {5.0182478202557746902556648e+00, -1.6259990074019058442232221e+00}, - {1.0861137372799545160704002e+01, 2.0502936359659111755031062e+00}, - {1.0070841084922199607011905e+01, 2.9483213155446756211881774e-01}, - {5.9922447613166942183705192e+00, 1.0605860367252556281902109e+00}, - {5.8978784056736762299945176e+00, 4.8084556083358307819310911e-01}, - {3.2822866700678709020367184e+00, 5.8969634164776659423195222e-01}, - {8.8756430028990417290744307e+00, -1.3636647724582455028314573e+00}, - {1.0011785496777731986390856e+01, 2.6210913895386013290915234e+00}, -} -var pow = []complex128{ - (-2.499956739197529585028819e+00 + 1.759751724335650228957144e+00i), - (7.357094338218116311191939e+04 - 5.089973412479151648145882e+04i), - (1.320777296067768517259592e+01 - 3.165621914333901498921986e+01i), - (-3.123287828297300934072149e-07 - 1.9849567521490553032502223E-7i), - (8.0622651468477229614813e+04 - 7.80028727944573092944363e+04i), - (-1.0268824572103165858577141e+00 - 4.716844738244989776610672e-01i), - (-4.35953819012244175753187e+01 + 2.2036445974645306917648585e+02i), - (8.3556092283250594950239e-01 - 1.2261571947167240272593282e+01i), - (1.582292972120769306069625e+03 + 1.273564263524278244782512e+04i), - (6.592208301642122149025369e-08 + 2.584887236651661903526389e-08i), -} -var sin = []complex128{ - (-1.1073801774240233539648544e+03 + 3.024539773002502192425231e+02i), - (1.0317037521400759359744682e+00 - 3.2208979799929570242818e-02i), - (-2.0501952097271429804261058e+01 - 7.2137981348240798841800967e+01i), - (7.3173638080346338642193078e+03 + 2.249219506193664342566248e+03i), - (-1.964375633631808177565226e+00 - 9.0958264713870404464159683e+00i), - (1.992783647158514838337674e+01 - 9.11555769410191350416942e+01i), - (-6.680335650741921444300349e+00 + 3.763353833142432513086117e+00i), - (1.2794028166657459148245993e+00 - 2.7669092099795781155109602e+00i), - (2.8641693949535259594188879e+03 + 7.451234399649871202841615e+02i), - (-4.893811726244659135553033e+01 - 5.371469305562194635957655e+01i), -} -var sinh = []complex128{ - (8.34559353341652565758198e+00 + 7.2187893208650790476628899e+01i), - (1.1042192548260646752051112e+03 - 3.1379650595631635858792056e+02i), - (-8.239469336509264113041849e-02 + 9.9273668758439489098514519e-01i), - (7.332295456982297798219401e+01 - 1.574585908122833444899023e+01i), - (-7.4786432301380582103534216e+03 + 1.63483823493980029604071e+03i), - (4.595842179016870234028347e+00 - 8.135290105518580753211484e+00i), - (-8.543842533574163435246793e+01 + 3.750798997857594068272375e+01i), - (-1.918003500809465688017307e+00 + 7.4358344619793504041350251e+00i), - (-2.233816733239658031433147e+00 - 2.143519070805995056229335e+00i), - (-7.797564130187551181105341e+02 - 2.8549352346594918614806877e+03i), -} -var sqrt = []complex128{ - (2.6628203086086130543813948e+00 + 1.4531345674282185229796902e+00i), - (2.7823278427251986247149295e+00 - 4.9756907317005224529115567e-02i), - (1.5397025302089642757361015e+00 - 1.6271336573016637535695727e+00i), - (1.7103411581506875260277898e+00 + 2.8170677122737589676157029e+00i), - (3.1390392472953103383607947e+00 + 4.6612625849858653248980849e-01i), - (2.1117080764822417640789287e+00 + 1.2381170223514273234967850e+00i), - (2.3587032281672256703926939e+00 + 5.7827111903257349935720172e-01i), - (1.7335262588873410476661577e+00 + 5.2647258220721269141550382e-01i), - (2.3131094974708716531499282e+00 - 1.8775429304303785570775490e+00i), - (8.1420535745048086240947359e-01 + 3.0575897587277248522656113e+00i), -} -var tan = []complex128{ - (-1.928757919086441129134525e-07 + 1.0000003267499169073251826e+00i), - (1.242412685364183792138948e+00 - 3.17149693883133370106696e+00i), - (-4.6745126251587795225571826e-05 - 9.9992439225263959286114298e-01i), - (4.792363401193648192887116e-09 + 1.0000000070589333451557723e+00i), - (2.345740824080089140287315e-03 + 9.947733046570988661022763e-01i), - (-2.396030789494815566088809e-05 + 9.9994781345418591429826779e-01i), - (-7.370204836644931340905303e-03 + 1.0043553413417138987717748e+00i), - (-3.691803847992048527007457e-02 + 9.6475071993469548066328894e-01i), - (-2.781955256713729368401878e-08 - 1.000000049848910609006646e+00i), - (9.4281590064030478879791249e-05 + 9.9999119340863718183758545e-01i), -} -var tanh = []complex128{ - (1.0000921981225144748819918e+00 + 2.160986245871518020231507e-05i), - (9.9999967727531993209562591e-01 - 1.9953763222959658873657676e-07i), - (-1.765485739548037260789686e+00 + 1.7024216325552852445168471e+00i), - (-9.999189442732736452807108e-01 + 3.64906070494473701938098e-05i), - (9.9999999224622333738729767e-01 - 3.560088949517914774813046e-09i), - (1.0029324933367326862499343e+00 - 4.948790309797102353137528e-03i), - (9.9996113064788012488693567e-01 - 4.226995742097032481451259e-05i), - (1.0074784189316340029873945e+00 - 4.194050814891697808029407e-03i), - (9.9385534229718327109131502e-01 + 5.144217985914355502713437e-02i), - (-1.0000000491604982429364892e+00 - 2.901873195374433112227349e-08i), -} - -// special cases -var vcAbsSC = []complex128{ - NaN(), -} -var absSC = []float64{ - math.NaN(), -} -var vcAcosSC = []complex128{ - NaN(), -} -var acosSC = []complex128{ - NaN(), -} -var vcAcoshSC = []complex128{ - NaN(), -} -var acoshSC = []complex128{ - NaN(), -} -var vcAsinSC = []complex128{ - NaN(), -} -var asinSC = []complex128{ - NaN(), -} -var vcAsinhSC = []complex128{ - NaN(), -} -var asinhSC = []complex128{ - NaN(), -} -var vcAtanSC = []complex128{ - NaN(), -} -var atanSC = []complex128{ - NaN(), -} -var vcAtanhSC = []complex128{ - NaN(), -} -var atanhSC = []complex128{ - NaN(), -} -var vcConjSC = []complex128{ - NaN(), -} -var conjSC = []complex128{ - NaN(), -} -var vcCosSC = []complex128{ - NaN(), -} -var cosSC = []complex128{ - NaN(), -} -var vcCoshSC = []complex128{ - NaN(), -} -var coshSC = []complex128{ - NaN(), -} -var vcExpSC = []complex128{ - NaN(), -} -var expSC = []complex128{ - NaN(), -} -var vcIsNaNSC = []complex128{ - complex(math.Inf(-1), math.Inf(-1)), - complex(math.Inf(-1), math.NaN()), - complex(math.NaN(), math.Inf(-1)), - complex(0, math.NaN()), - complex(math.NaN(), 0), - complex(math.Inf(1), math.Inf(1)), - complex(math.Inf(1), math.NaN()), - complex(math.NaN(), math.Inf(1)), - complex(math.NaN(), math.NaN()), -} -var isNaNSC = []bool{ - false, - false, - false, - true, - true, - false, - false, - false, - true, -} -var vcLogSC = []complex128{ - NaN(), -} -var logSC = []complex128{ - NaN(), -} -var vcLog10SC = []complex128{ - NaN(), -} -var log10SC = []complex128{ - NaN(), -} -var vcPolarSC = []complex128{ - NaN(), -} -var polarSC = []ff{ - {math.NaN(), math.NaN()}, -} -var vcPowSC = [][2]complex128{ - {NaN(), NaN()}, -} -var powSC = []complex128{ - NaN(), -} -var vcSinSC = []complex128{ - NaN(), -} -var sinSC = []complex128{ - NaN(), -} -var vcSinhSC = []complex128{ - NaN(), -} -var sinhSC = []complex128{ - NaN(), -} -var vcSqrtSC = []complex128{ - NaN(), -} -var sqrtSC = []complex128{ - NaN(), -} -var vcTanSC = []complex128{ - NaN(), -} -var tanSC = []complex128{ - NaN(), -} -var vcTanhSC = []complex128{ - NaN(), -} -var tanhSC = []complex128{ - NaN(), -} - -// functions borrowed from pkg/math/all_test.go -func tolerance(a, b, e float64) bool { - d := a - b - if d < 0 { - d = -d - } - - if a != 0 { - e = e * a - if e < 0 { - e = -e - } - } - return d < e -} -func soclose(a, b, e float64) bool { return tolerance(a, b, e) } -func veryclose(a, b float64) bool { return tolerance(a, b, 4e-16) } -func alike(a, b float64) bool { - switch { - case a != a && b != b: // math.IsNaN(a) && math.IsNaN(b): - return true - case a == b: - return math.Signbit(a) == math.Signbit(b) - } - return false -} - -func cTolerance(a, b complex128, e float64) bool { - d := Abs(a - b) - if a != 0 { - e = e * Abs(a) - if e < 0 { - e = -e - } - } - return d < e -} -func cSoclose(a, b complex128, e float64) bool { return cTolerance(a, b, e) } -func cVeryclose(a, b complex128) bool { return cTolerance(a, b, 4e-16) } -func cAlike(a, b complex128) bool { - switch { - case IsNaN(a) && IsNaN(b): - return true - case a == b: - return math.Signbit(real(a)) == math.Signbit(real(b)) && math.Signbit(imag(a)) == math.Signbit(imag(b)) - } - return false -} - -func TestAbs(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Abs(vc[i]); !veryclose(abs[i], f) { - t.Errorf("Abs(%g) = %g, want %g", vc[i], f, abs[i]) - } - } - for i := 0; i < len(vcAbsSC); i++ { - if f := Abs(vcAbsSC[i]); !alike(absSC[i], f) { - t.Errorf("Abs(%g) = %g, want %g", vcAbsSC[i], f, absSC[i]) - } - } -} -func TestAcos(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Acos(vc[i]); !cSoclose(acos[i], f, 1e-14) { - t.Errorf("Acos(%g) = %g, want %g", vc[i], f, acos[i]) - } - } - for i := 0; i < len(vcAcosSC); i++ { - if f := Acos(vcAcosSC[i]); !cAlike(acosSC[i], f) { - t.Errorf("Acos(%g) = %g, want %g", vcAcosSC[i], f, acosSC[i]) - } - } -} -func TestAcosh(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Acosh(vc[i]); !cSoclose(acosh[i], f, 1e-14) { - t.Errorf("Acosh(%g) = %g, want %g", vc[i], f, acosh[i]) - } - } - for i := 0; i < len(vcAcoshSC); i++ { - if f := Acosh(vcAcoshSC[i]); !cAlike(acoshSC[i], f) { - t.Errorf("Acosh(%g) = %g, want %g", vcAcoshSC[i], f, acoshSC[i]) - } - } -} -func TestAsin(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Asin(vc[i]); !cSoclose(asin[i], f, 1e-14) { - t.Errorf("Asin(%g) = %g, want %g", vc[i], f, asin[i]) - } - } - for i := 0; i < len(vcAsinSC); i++ { - if f := Asin(vcAsinSC[i]); !cAlike(asinSC[i], f) { - t.Errorf("Asin(%g) = %g, want %g", vcAsinSC[i], f, asinSC[i]) - } - } -} -func TestAsinh(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Asinh(vc[i]); !cSoclose(asinh[i], f, 4e-15) { - t.Errorf("Asinh(%g) = %g, want %g", vc[i], f, asinh[i]) - } - } - for i := 0; i < len(vcAsinhSC); i++ { - if f := Asinh(vcAsinhSC[i]); !cAlike(asinhSC[i], f) { - t.Errorf("Asinh(%g) = %g, want %g", vcAsinhSC[i], f, asinhSC[i]) - } - } -} -func TestAtan(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Atan(vc[i]); !cVeryclose(atan[i], f) { - t.Errorf("Atan(%g) = %g, want %g", vc[i], f, atan[i]) - } - } - for i := 0; i < len(vcAtanSC); i++ { - if f := Atan(vcAtanSC[i]); !cAlike(atanSC[i], f) { - t.Errorf("Atan(%g) = %g, want %g", vcAtanSC[i], f, atanSC[i]) - } - } -} -func TestAtanh(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Atanh(vc[i]); !cVeryclose(atanh[i], f) { - t.Errorf("Atanh(%g) = %g, want %g", vc[i], f, atanh[i]) - } - } - for i := 0; i < len(vcAtanhSC); i++ { - if f := Atanh(vcAtanhSC[i]); !cAlike(atanhSC[i], f) { - t.Errorf("Atanh(%g) = %g, want %g", vcAtanhSC[i], f, atanhSC[i]) - } - } -} -func TestConj(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Conj(vc[i]); !cVeryclose(conj[i], f) { - t.Errorf("Conj(%g) = %g, want %g", vc[i], f, conj[i]) - } - } - for i := 0; i < len(vcConjSC); i++ { - if f := Conj(vcConjSC[i]); !cAlike(conjSC[i], f) { - t.Errorf("Conj(%g) = %g, want %g", vcConjSC[i], f, conjSC[i]) - } - } -} -func TestCos(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Cos(vc[i]); !cSoclose(cos[i], f, 3e-15) { - t.Errorf("Cos(%g) = %g, want %g", vc[i], f, cos[i]) - } - } - for i := 0; i < len(vcCosSC); i++ { - if f := Cos(vcCosSC[i]); !cAlike(cosSC[i], f) { - t.Errorf("Cos(%g) = %g, want %g", vcCosSC[i], f, cosSC[i]) - } - } -} -func TestCosh(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Cosh(vc[i]); !cSoclose(cosh[i], f, 2e-15) { - t.Errorf("Cosh(%g) = %g, want %g", vc[i], f, cosh[i]) - } - } - for i := 0; i < len(vcCoshSC); i++ { - if f := Cosh(vcCoshSC[i]); !cAlike(coshSC[i], f) { - t.Errorf("Cosh(%g) = %g, want %g", vcCoshSC[i], f, coshSC[i]) - } - } -} -func TestExp(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Exp(vc[i]); !cSoclose(exp[i], f, 1e-15) { - t.Errorf("Exp(%g) = %g, want %g", vc[i], f, exp[i]) - } - } - for i := 0; i < len(vcExpSC); i++ { - if f := Exp(vcExpSC[i]); !cAlike(expSC[i], f) { - t.Errorf("Exp(%g) = %g, want %g", vcExpSC[i], f, expSC[i]) - } - } -} -func TestIsNaN(t *testing.T) { - for i := 0; i < len(vcIsNaNSC); i++ { - if f := IsNaN(vcIsNaNSC[i]); isNaNSC[i] != f { - t.Errorf("IsNaN(%v) = %v, want %v", vcIsNaNSC[i], f, isNaNSC[i]) - } - } -} -func TestLog(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Log(vc[i]); !cVeryclose(log[i], f) { - t.Errorf("Log(%g) = %g, want %g", vc[i], f, log[i]) - } - } - for i := 0; i < len(vcLogSC); i++ { - if f := Log(vcLogSC[i]); !cAlike(logSC[i], f) { - t.Errorf("Log(%g) = %g, want %g", vcLogSC[i], f, logSC[i]) - } - } -} -func TestLog10(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Log10(vc[i]); !cVeryclose(log10[i], f) { - t.Errorf("Log10(%g) = %g, want %g", vc[i], f, log10[i]) - } - } - for i := 0; i < len(vcLog10SC); i++ { - if f := Log10(vcLog10SC[i]); !cAlike(log10SC[i], f) { - t.Errorf("Log10(%g) = %g, want %g", vcLog10SC[i], f, log10SC[i]) - } - } -} -func TestPolar(t *testing.T) { - for i := 0; i < len(vc); i++ { - if r, theta := Polar(vc[i]); !veryclose(polar[i].r, r) && !veryclose(polar[i].theta, theta) { - t.Errorf("Polar(%g) = %g, %g want %g, %g", vc[i], r, theta, polar[i].r, polar[i].theta) - } - } - for i := 0; i < len(vcPolarSC); i++ { - if r, theta := Polar(vcPolarSC[i]); !alike(polarSC[i].r, r) && !alike(polarSC[i].theta, theta) { - t.Errorf("Polar(%g) = %g, %g, want %g, %g", vcPolarSC[i], r, theta, polarSC[i].r, polarSC[i].theta) - } - } -} -func TestPow(t *testing.T) { - var a = complex(3.0, 3.0) - for i := 0; i < len(vc); i++ { - if f := Pow(a, vc[i]); !cSoclose(pow[i], f, 4e-15) { - t.Errorf("Pow(%g, %g) = %g, want %g", a, vc[i], f, pow[i]) - } - } - for i := 0; i < len(vcPowSC); i++ { - if f := Pow(vcPowSC[i][0], vcPowSC[i][0]); !cAlike(powSC[i], f) { - t.Errorf("Pow(%g, %g) = %g, want %g", vcPowSC[i][0], vcPowSC[i][0], f, powSC[i]) - } - } -} -func TestRect(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Rect(polar[i].r, polar[i].theta); !cVeryclose(vc[i], f) { - t.Errorf("Rect(%g, %g) = %g want %g", polar[i].r, polar[i].theta, f, vc[i]) - } - } - for i := 0; i < len(vcPolarSC); i++ { - if f := Rect(polarSC[i].r, polarSC[i].theta); !cAlike(vcPolarSC[i], f) { - t.Errorf("Rect(%g, %g) = %g, want %g", polarSC[i].r, polarSC[i].theta, f, vcPolarSC[i]) - } - } -} -func TestSin(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Sin(vc[i]); !cSoclose(sin[i], f, 2e-15) { - t.Errorf("Sin(%g) = %g, want %g", vc[i], f, sin[i]) - } - } - for i := 0; i < len(vcSinSC); i++ { - if f := Sin(vcSinSC[i]); !cAlike(sinSC[i], f) { - t.Errorf("Sin(%g) = %g, want %g", vcSinSC[i], f, sinSC[i]) - } - } -} -func TestSinh(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Sinh(vc[i]); !cSoclose(sinh[i], f, 2e-15) { - t.Errorf("Sinh(%g) = %g, want %g", vc[i], f, sinh[i]) - } - } - for i := 0; i < len(vcSinhSC); i++ { - if f := Sinh(vcSinhSC[i]); !cAlike(sinhSC[i], f) { - t.Errorf("Sinh(%g) = %g, want %g", vcSinhSC[i], f, sinhSC[i]) - } - } -} -func TestSqrt(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Sqrt(vc[i]); !cVeryclose(sqrt[i], f) { - t.Errorf("Sqrt(%g) = %g, want %g", vc[i], f, sqrt[i]) - } - } - for i := 0; i < len(vcSqrtSC); i++ { - if f := Sqrt(vcSqrtSC[i]); !cAlike(sqrtSC[i], f) { - t.Errorf("Sqrt(%g) = %g, want %g", vcSqrtSC[i], f, sqrtSC[i]) - } - } -} -func TestTan(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Tan(vc[i]); !cSoclose(tan[i], f, 3e-15) { - t.Errorf("Tan(%g) = %g, want %g", vc[i], f, tan[i]) - } - } - for i := 0; i < len(vcTanSC); i++ { - if f := Tan(vcTanSC[i]); !cAlike(tanSC[i], f) { - t.Errorf("Tan(%g) = %g, want %g", vcTanSC[i], f, tanSC[i]) - } - } -} -func TestTanh(t *testing.T) { - for i := 0; i < len(vc); i++ { - if f := Tanh(vc[i]); !cSoclose(tanh[i], f, 2e-15) { - t.Errorf("Tanh(%g) = %g, want %g", vc[i], f, tanh[i]) - } - } - for i := 0; i < len(vcTanhSC); i++ { - if f := Tanh(vcTanhSC[i]); !cAlike(tanhSC[i], f) { - t.Errorf("Tanh(%g) = %g, want %g", vcTanhSC[i], f, tanhSC[i]) - } - } -} - -func BenchmarkAbs(b *testing.B) { - for i := 0; i < b.N; i++ { - Abs(complex(2.5, 3.5)) - } -} -func BenchmarkAcos(b *testing.B) { - for i := 0; i < b.N; i++ { - Acos(complex(2.5, 3.5)) - } -} -func BenchmarkAcosh(b *testing.B) { - for i := 0; i < b.N; i++ { - Acosh(complex(2.5, 3.5)) - } -} -func BenchmarkAsin(b *testing.B) { - for i := 0; i < b.N; i++ { - Asin(complex(2.5, 3.5)) - } -} -func BenchmarkAsinh(b *testing.B) { - for i := 0; i < b.N; i++ { - Asinh(complex(2.5, 3.5)) - } -} -func BenchmarkAtan(b *testing.B) { - for i := 0; i < b.N; i++ { - Atan(complex(2.5, 3.5)) - } -} -func BenchmarkAtanh(b *testing.B) { - for i := 0; i < b.N; i++ { - Atanh(complex(2.5, 3.5)) - } -} -func BenchmarkConj(b *testing.B) { - for i := 0; i < b.N; i++ { - Conj(complex(2.5, 3.5)) - } -} -func BenchmarkCos(b *testing.B) { - for i := 0; i < b.N; i++ { - Cos(complex(2.5, 3.5)) - } -} -func BenchmarkCosh(b *testing.B) { - for i := 0; i < b.N; i++ { - Cosh(complex(2.5, 3.5)) - } -} -func BenchmarkExp(b *testing.B) { - for i := 0; i < b.N; i++ { - Exp(complex(2.5, 3.5)) - } -} -func BenchmarkLog(b *testing.B) { - for i := 0; i < b.N; i++ { - Log(complex(2.5, 3.5)) - } -} -func BenchmarkLog10(b *testing.B) { - for i := 0; i < b.N; i++ { - Log10(complex(2.5, 3.5)) - } -} -func BenchmarkPhase(b *testing.B) { - for i := 0; i < b.N; i++ { - Phase(complex(2.5, 3.5)) - } -} -func BenchmarkPolar(b *testing.B) { - for i := 0; i < b.N; i++ { - Polar(complex(2.5, 3.5)) - } -} -func BenchmarkPow(b *testing.B) { - for i := 0; i < b.N; i++ { - Pow(complex(2.5, 3.5), complex(2.5, 3.5)) - } -} -func BenchmarkRect(b *testing.B) { - for i := 0; i < b.N; i++ { - Rect(2.5, 1.5) - } -} -func BenchmarkSin(b *testing.B) { - for i := 0; i < b.N; i++ { - Sin(complex(2.5, 3.5)) - } -} -func BenchmarkSinh(b *testing.B) { - for i := 0; i < b.N; i++ { - Sinh(complex(2.5, 3.5)) - } -} -func BenchmarkSqrt(b *testing.B) { - for i := 0; i < b.N; i++ { - Sqrt(complex(2.5, 3.5)) - } -} -func BenchmarkTan(b *testing.B) { - for i := 0; i < b.N; i++ { - Tan(complex(2.5, 3.5)) - } -} -func BenchmarkTanh(b *testing.B) { - for i := 0; i < b.N; i++ { - Tanh(complex(2.5, 3.5)) - } -} diff --git a/libgo/go/cmath/conj.go b/libgo/go/cmath/conj.go deleted file mode 100644 index 776b57d..0000000 --- a/libgo/go/cmath/conj.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -// Conj returns the complex conjugate of x. -func Conj(x complex128) complex128 { return complex(real(x), -imag(x)) } diff --git a/libgo/go/cmath/exp.go b/libgo/go/cmath/exp.go deleted file mode 100644 index 64c1ef4..0000000 --- a/libgo/go/cmath/exp.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// The original C code, the long comment, and the constants -// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. -// The go code is a simplified version of the original C. -// -// Cephes Math Library Release 2.8: June, 2000 -// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -// -// The readme file at http://netlib.sandia.gov/cephes/ says: -// Some software in this archive may be from the book _Methods and -// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster -// International, 1989) or from the Cephes Mathematical Library, a -// commercial product. In either event, it is copyrighted by the author. -// What you see here may be used freely but it comes with no support or -// guarantee. -// -// The two known misprints in the book are repaired here in the -// source listings for the gamma function and the incomplete beta -// integral. -// -// Stephen L. Moshier -// moshier@na-net.ornl.gov - -// Complex exponential function -// -// DESCRIPTION: -// -// Returns the complex exponential of the complex argument z. -// -// If -// z = x + iy, -// r = exp(x), -// then -// w = r cos y + i r sin y. -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 8700 3.7e-17 1.1e-17 -// IEEE -10,+10 30000 3.0e-16 8.7e-17 - -// Exp returns e**x, the base-e exponential of x. -func Exp(x complex128) complex128 { - r := math.Exp(real(x)) - s, c := math.Sincos(imag(x)) - return complex(r*c, r*s) -} diff --git a/libgo/go/cmath/isinf.go b/libgo/go/cmath/isinf.go deleted file mode 100644 index f23d2dea..0000000 --- a/libgo/go/cmath/isinf.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// IsInf returns true if either real(x) or imag(x) is an infinity. -func IsInf(x complex128) bool { - if math.IsInf(real(x), 0) || math.IsInf(imag(x), 0) { - return true - } - return false -} - -// Inf returns a complex infinity, complex(+Inf, +Inf). -func Inf() complex128 { - inf := math.Inf(1) - return complex(inf, inf) -} diff --git a/libgo/go/cmath/isnan.go b/libgo/go/cmath/isnan.go deleted file mode 100644 index 2063bb8..0000000 --- a/libgo/go/cmath/isnan.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// IsNaN returns true if either real(x) or imag(x) is NaN -// and neither is an infinity. -func IsNaN(x complex128) bool { - switch { - case math.IsInf(real(x), 0) || math.IsInf(imag(x), 0): - return false - case math.IsNaN(real(x)) || math.IsNaN(imag(x)): - return true - } - return false -} - -// NaN returns a complex ``not-a-number'' value. -func NaN() complex128 { - nan := math.NaN() - return complex(nan, nan) -} diff --git a/libgo/go/cmath/log.go b/libgo/go/cmath/log.go deleted file mode 100644 index 8e6964f..0000000 --- a/libgo/go/cmath/log.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// The original C code, the long comment, and the constants -// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. -// The go code is a simplified version of the original C. -// -// Cephes Math Library Release 2.8: June, 2000 -// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -// -// The readme file at http://netlib.sandia.gov/cephes/ says: -// Some software in this archive may be from the book _Methods and -// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster -// International, 1989) or from the Cephes Mathematical Library, a -// commercial product. In either event, it is copyrighted by the author. -// What you see here may be used freely but it comes with no support or -// guarantee. -// -// The two known misprints in the book are repaired here in the -// source listings for the gamma function and the incomplete beta -// integral. -// -// Stephen L. Moshier -// moshier@na-net.ornl.gov - -// Complex natural logarithm -// -// DESCRIPTION: -// -// Returns complex logarithm to the base e (2.718...) of -// the complex argument z. -// -// If -// z = x + iy, r = sqrt( x**2 + y**2 ), -// then -// w = log(r) + i arctan(y/x). -// -// The arctangent ranges from -PI to +PI. -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 7000 8.5e-17 1.9e-17 -// IEEE -10,+10 30000 5.0e-15 1.1e-16 -// -// Larger relative error can be observed for z near 1 +i0. -// In IEEE arithmetic the peak absolute error is 5.2e-16, rms -// absolute error 1.0e-16. - -// Log returns the natural logarithm of x. -func Log(x complex128) complex128 { - return complex(math.Log(Abs(x)), Phase(x)) -} - -// Log10 returns the decimal logarithm of x. -func Log10(x complex128) complex128 { - return math.Log10E * Log(x) -} diff --git a/libgo/go/cmath/phase.go b/libgo/go/cmath/phase.go deleted file mode 100644 index 2d67aa3..0000000 --- a/libgo/go/cmath/phase.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// Phase returns the phase (also called the argument) of x. -// The returned value is in the range [-Pi, Pi]. -func Phase(x complex128) float64 { return math.Atan2(imag(x), real(x)) } diff --git a/libgo/go/cmath/polar.go b/libgo/go/cmath/polar.go deleted file mode 100644 index 033676a..0000000 --- a/libgo/go/cmath/polar.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -// Polar returns the absolute value r and phase θ of x, -// such that x = r * e**θi. -// The phase is in the range [-Pi, Pi]. -func Polar(x complex128) (r, θ float64) { - return Abs(x), Phase(x) -} diff --git a/libgo/go/cmath/pow.go b/libgo/go/cmath/pow.go deleted file mode 100644 index 68e1207..0000000 --- a/libgo/go/cmath/pow.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// The original C code, the long comment, and the constants -// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. -// The go code is a simplified version of the original C. -// -// Cephes Math Library Release 2.8: June, 2000 -// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -// -// The readme file at http://netlib.sandia.gov/cephes/ says: -// Some software in this archive may be from the book _Methods and -// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster -// International, 1989) or from the Cephes Mathematical Library, a -// commercial product. In either event, it is copyrighted by the author. -// What you see here may be used freely but it comes with no support or -// guarantee. -// -// The two known misprints in the book are repaired here in the -// source listings for the gamma function and the incomplete beta -// integral. -// -// Stephen L. Moshier -// moshier@na-net.ornl.gov - -// Complex power function -// -// DESCRIPTION: -// -// Raises complex A to the complex Zth power. -// Definition is per AMS55 # 4.2.8, -// analytically equivalent to cpow(a,z) = cexp(z clog(a)). -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// IEEE -10,+10 30000 9.4e-15 1.5e-15 - -// Pow returns x**y, the base-x exponential of y. -func Pow(x, y complex128) complex128 { - modulus := Abs(x) - if modulus == 0 { - return complex(0, 0) - } - r := math.Pow(modulus, real(y)) - arg := Phase(x) - theta := real(y) * arg - if imag(y) != 0 { - r *= math.Exp(-imag(y) * arg) - theta += imag(y) * math.Log(modulus) - } - s, c := math.Sincos(theta) - return complex(r*c, r*s) -} diff --git a/libgo/go/cmath/rect.go b/libgo/go/cmath/rect.go deleted file mode 100644 index b955f0b..0000000 --- a/libgo/go/cmath/rect.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// Rect returns the complex number x with polar coordinates r, θ. -func Rect(r, θ float64) complex128 { - s, c := math.Sincos(θ) - return complex(r*c, r*s) -} diff --git a/libgo/go/cmath/sin.go b/libgo/go/cmath/sin.go deleted file mode 100644 index 486b717..0000000 --- a/libgo/go/cmath/sin.go +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// The original C code, the long comment, and the constants -// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. -// The go code is a simplified version of the original C. -// -// Cephes Math Library Release 2.8: June, 2000 -// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -// -// The readme file at http://netlib.sandia.gov/cephes/ says: -// Some software in this archive may be from the book _Methods and -// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster -// International, 1989) or from the Cephes Mathematical Library, a -// commercial product. In either event, it is copyrighted by the author. -// What you see here may be used freely but it comes with no support or -// guarantee. -// -// The two known misprints in the book are repaired here in the -// source listings for the gamma function and the incomplete beta -// integral. -// -// Stephen L. Moshier -// moshier@na-net.ornl.gov - -// Complex circular sine -// -// DESCRIPTION: -// -// If -// z = x + iy, -// -// then -// -// w = sin x cosh y + i cos x sinh y. -// -// csin(z) = -i csinh(iz). -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 8400 5.3e-17 1.3e-17 -// IEEE -10,+10 30000 3.8e-16 1.0e-16 -// Also tested by csin(casin(z)) = z. - -// Sin returns the sine of x. -func Sin(x complex128) complex128 { - s, c := math.Sincos(real(x)) - sh, ch := sinhcosh(imag(x)) - return complex(s*ch, c*sh) -} - -// Complex hyperbolic sine -// -// DESCRIPTION: -// -// csinh z = (cexp(z) - cexp(-z))/2 -// = sinh x * cos y + i cosh x * sin y . -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// IEEE -10,+10 30000 3.1e-16 8.2e-17 - -// Sinh returns the hyperbolic sine of x. -func Sinh(x complex128) complex128 { - s, c := math.Sincos(imag(x)) - sh, ch := sinhcosh(real(x)) - return complex(c*sh, s*ch) -} - -// Complex circular cosine -// -// DESCRIPTION: -// -// If -// z = x + iy, -// -// then -// -// w = cos x cosh y - i sin x sinh y. -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 8400 4.5e-17 1.3e-17 -// IEEE -10,+10 30000 3.8e-16 1.0e-16 - -// Cos returns the cosine of x. -func Cos(x complex128) complex128 { - s, c := math.Sincos(real(x)) - sh, ch := sinhcosh(imag(x)) - return complex(c*ch, -s*sh) -} - -// Complex hyperbolic cosine -// -// DESCRIPTION: -// -// ccosh(z) = cosh x cos y + i sinh x sin y . -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// IEEE -10,+10 30000 2.9e-16 8.1e-17 - -// Cosh returns the hyperbolic cosine of x. -func Cosh(x complex128) complex128 { - s, c := math.Sincos(imag(x)) - sh, ch := sinhcosh(real(x)) - return complex(c*ch, s*sh) -} - -// calculate sinh and cosh -func sinhcosh(x float64) (sh, ch float64) { - if math.Abs(x) <= 0.5 { - return math.Sinh(x), math.Cosh(x) - } - e := math.Exp(x) - ei := 0.5 / e - e *= 0.5 - return e - ei, e + ei -} diff --git a/libgo/go/cmath/sqrt.go b/libgo/go/cmath/sqrt.go deleted file mode 100644 index 4e7e805..0000000 --- a/libgo/go/cmath/sqrt.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// The original C code, the long comment, and the constants -// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. -// The go code is a simplified version of the original C. -// -// Cephes Math Library Release 2.8: June, 2000 -// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -// -// The readme file at http://netlib.sandia.gov/cephes/ says: -// Some software in this archive may be from the book _Methods and -// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster -// International, 1989) or from the Cephes Mathematical Library, a -// commercial product. In either event, it is copyrighted by the author. -// What you see here may be used freely but it comes with no support or -// guarantee. -// -// The two known misprints in the book are repaired here in the -// source listings for the gamma function and the incomplete beta -// integral. -// -// Stephen L. Moshier -// moshier@na-net.ornl.gov - -// Complex square root -// -// DESCRIPTION: -// -// If z = x + iy, r = |z|, then -// -// 1/2 -// Re w = [ (r + x)/2 ] , -// -// 1/2 -// Im w = [ (r - x)/2 ] . -// -// Cancellation error in r-x or r+x is avoided by using the -// identity 2 Re w Im w = y. -// -// Note that -w is also a square root of z. The root chosen -// is always in the right half plane and Im w has the same sign as y. -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 25000 3.2e-17 9.6e-18 -// IEEE -10,+10 1,000,000 2.9e-16 6.1e-17 - -// Sqrt returns the square root of x. -func Sqrt(x complex128) complex128 { - if imag(x) == 0 { - if real(x) == 0 { - return complex(0, 0) - } - if real(x) < 0 { - return complex(0, math.Sqrt(-real(x))) - } - return complex(math.Sqrt(real(x)), 0) - } - if real(x) == 0 { - if imag(x) < 0 { - r := math.Sqrt(-0.5 * imag(x)) - return complex(r, -r) - } - r := math.Sqrt(0.5 * imag(x)) - return complex(r, r) - } - a := real(x) - b := imag(x) - var scale float64 - // Rescale to avoid internal overflow or underflow. - if math.Abs(a) > 4 || math.Abs(b) > 4 { - a *= 0.25 - b *= 0.25 - scale = 2 - } else { - a *= 1.8014398509481984e16 // 2**54 - b *= 1.8014398509481984e16 - scale = 7.450580596923828125e-9 // 2**-27 - } - r := math.Hypot(a, b) - var t float64 - if a > 0 { - t = math.Sqrt(0.5*r + 0.5*a) - r = scale * math.Abs((0.5*b)/t) - t *= scale - } else { - r = math.Sqrt(0.5*r - 0.5*a) - t = scale * math.Abs((0.5*b)/r) - r *= scale - } - if b < 0 { - return complex(t, -r) - } - return complex(t, r) -} diff --git a/libgo/go/cmath/tan.go b/libgo/go/cmath/tan.go deleted file mode 100644 index 67dc22a..0000000 --- a/libgo/go/cmath/tan.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cmath - -import "math" - -// The original C code, the long comment, and the constants -// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. -// The go code is a simplified version of the original C. -// -// Cephes Math Library Release 2.8: June, 2000 -// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -// -// The readme file at http://netlib.sandia.gov/cephes/ says: -// Some software in this archive may be from the book _Methods and -// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster -// International, 1989) or from the Cephes Mathematical Library, a -// commercial product. In either event, it is copyrighted by the author. -// What you see here may be used freely but it comes with no support or -// guarantee. -// -// The two known misprints in the book are repaired here in the -// source listings for the gamma function and the incomplete beta -// integral. -// -// Stephen L. Moshier -// moshier@na-net.ornl.gov - -// Complex circular tangent -// -// DESCRIPTION: -// -// If -// z = x + iy, -// -// then -// -// sin 2x + i sinh 2y -// w = --------------------. -// cos 2x + cosh 2y -// -// On the real axis the denominator is zero at odd multiples -// of PI/2. The denominator is evaluated by its Taylor -// series near these points. -// -// ctan(z) = -i ctanh(iz). -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 5200 7.1e-17 1.6e-17 -// IEEE -10,+10 30000 7.2e-16 1.2e-16 -// Also tested by ctan * ccot = 1 and catan(ctan(z)) = z. - -// Tan returns the tangent of x. -func Tan(x complex128) complex128 { - d := math.Cos(2*real(x)) + math.Cosh(2*imag(x)) - if math.Abs(d) < 0.25 { - d = tanSeries(x) - } - if d == 0 { - return Inf() - } - return complex(math.Sin(2*real(x))/d, math.Sinh(2*imag(x))/d) -} - -// Complex hyperbolic tangent -// -// DESCRIPTION: -// -// tanh z = (sinh 2x + i sin 2y) / (cosh 2x + cos 2y) . -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// IEEE -10,+10 30000 1.7e-14 2.4e-16 - -// Tanh returns the hyperbolic tangent of x. -func Tanh(x complex128) complex128 { - d := math.Cosh(2*real(x)) + math.Cos(2*imag(x)) - if d == 0 { - return Inf() - } - return complex(math.Sinh(2*real(x))/d, math.Sin(2*imag(x))/d) -} - -// Program to subtract nearest integer multiple of PI -func reducePi(x float64) float64 { - const ( - // extended precision value of PI: - DP1 = 3.14159265160560607910E0 // ?? 0x400921fb54000000 - DP2 = 1.98418714791870343106E-9 // ?? 0x3e210b4610000000 - DP3 = 1.14423774522196636802E-17 // ?? 0x3c6a62633145c06e - ) - t := x / math.Pi - if t >= 0 { - t += 0.5 - } else { - t -= 0.5 - } - t = float64(int64(t)) // int64(t) = the multiple - return ((x - t*DP1) - t*DP2) - t*DP3 -} - -// Taylor series expansion for cosh(2y) - cos(2x) -func tanSeries(z complex128) float64 { - const MACHEP = 1.0 / (1 << 53) - x := math.Abs(2 * real(z)) - y := math.Abs(2 * imag(z)) - x = reducePi(x) - x = x * x - y = y * y - x2 := 1.0 - y2 := 1.0 - f := 1.0 - rn := 0.0 - d := 0.0 - for { - rn += 1 - f *= rn - rn += 1 - f *= rn - x2 *= x - y2 *= y - t := y2 + x2 - t /= f - d += t - - rn += 1 - f *= rn - rn += 1 - f *= rn - x2 *= x - y2 *= y - t = y2 - x2 - t /= f - d += t - if math.Abs(t/d) <= MACHEP { - break - } - } - return d -} - -// Complex circular cotangent -// -// DESCRIPTION: -// -// If -// z = x + iy, -// -// then -// -// sin 2x - i sinh 2y -// w = --------------------. -// cosh 2y - cos 2x -// -// On the real axis, the denominator has zeros at even -// multiples of PI/2. Near these points it is evaluated -// by a Taylor series. -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 3000 6.5e-17 1.6e-17 -// IEEE -10,+10 30000 9.2e-16 1.2e-16 -// Also tested by ctan * ccot = 1 + i0. - -// Cot returns the cotangent of x. -func Cot(x complex128) complex128 { - d := math.Cosh(2*imag(x)) - math.Cos(2*real(x)) - if math.Abs(d) < 0.25 { - d = tanSeries(x) - } - if d == 0 { - return Inf() - } - return complex(math.Sin(2*real(x))/d, -math.Sinh(2*imag(x))/d) -} diff --git a/libgo/go/compress/bzip2/bit_reader.go b/libgo/go/compress/bzip2/bit_reader.go index d058c14..b2c13e5 100644 --- a/libgo/go/compress/bzip2/bit_reader.go +++ b/libgo/go/compress/bzip2/bit_reader.go @@ -37,7 +37,7 @@ func newBitReader(r io.Reader) bitReader { // ReadBits64 reads the given number of bits and returns them in the // least-significant part of a uint64. In the event of an error, it returns 0 -// and the error can be obtained by calling Error(). +// and the error can be obtained by calling Err(). func (br *bitReader) ReadBits64(bits uint) (n uint64) { for bits > br.bits { b, err := br.r.ReadByte() @@ -82,6 +82,6 @@ func (br *bitReader) ReadBit() bool { return n != 0 } -func (br *bitReader) Error() error { +func (br *bitReader) Err() error { return br.err } diff --git a/libgo/go/compress/bzip2/bzip2.go b/libgo/go/compress/bzip2/bzip2.go index 343cca0..3dc8c62 100644 --- a/libgo/go/compress/bzip2/bzip2.go +++ b/libgo/go/compress/bzip2/bzip2.go @@ -80,7 +80,7 @@ func (bz2 *reader) Read(buf []byte) (n int, err error) { if !bz2.setupDone { err = bz2.setup() - brErr := bz2.br.Error() + brErr := bz2.br.Err() if brErr != nil { err = brErr } @@ -91,7 +91,7 @@ func (bz2 *reader) Read(buf []byte) (n int, err error) { } n, err = bz2.read(buf) - brErr := bz2.br.Error() + brErr := bz2.br.Err() if brErr != nil { err = brErr } diff --git a/libgo/go/compress/zlib/testdata/e.txt b/libgo/go/compress/zlib/testdata/e.txt deleted file mode 100644 index 76cf2a7..0000000 --- a/libgo/go/compress/zlib/testdata/e.txt +++ /dev/null @@ -1 +0,0 @@ -2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190115738341879307021540891499348841675092447614606680822648001684774118537423454424371075390777449920695517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416928368190255151086574637721112523897844250569536967707854499699679468644549059879316368892300987931277361782154249992295763514822082698951936680331825288693984964651058209392398294887933203625094431173012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509961818815930416903515988885193458072738667385894228792284998920868058257492796104841984443634632449684875602336248270419786232090021609902353043699418491463140934317381436405462531520961836908887070167683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354021234078498193343210681701210056278802351930332247450158539047304199577770935036604169973297250886876966403555707162268447162560798826517871341951246652010305921236677194325278675398558944896970964097545918569563802363701621120477427228364896134225164450781824423529486363721417402388934412479635743702637552944483379980161254922785092577825620926226483262779333865664816277251640191059004916449982893150566047258027786318641551956532442586982946959308019152987211725563475463964479101459040905862984967912874068705048958586717479854667757573205681288459205413340539220001137863009455606881667400169842055804033637953764520304024322566135278369511778838638744396625322498506549958862342818997077332761717839280349465014345588970719425863987727547109629537415211151368350627526023264847287039207643100595841166120545297030236472549296669381151373227536450988890313602057248176585118063036442812314965507047510254465011727211555194866850800368532281831521960037356252794495158284188294787610852639813955990067376482922443752871846245780361929819713991475644882626039033814418232625150974827987779964373089970388867782271383605772978824125611907176639465070633045279546618550966661856647097113444740160704626215680717481877844371436988218559670959102596862002353718588748569652200050311734392073211390803293634479727355955277349071783793421637012050054513263835440001863239914907054797780566978533580489669062951194324730995876552368128590413832411607226029983305353708761389396391779574540161372236187893652605381558415871869255386061647798340254351284396129460352913325942794904337299085731580290958631382683291477116396337092400316894586360606458459251269946557248391865642097526850823075442545993769170419777800853627309417101634349076964237222943523661255725088147792231519747780605696725380171807763603462459278778465850656050780844211529697521890874019660906651803516501792504619501366585436632712549639908549144200014574760819302212066024330096412704894390397177195180699086998606636583232278709376502260149291011517177635944602023249300280401867723910288097866605651183260043688508817157238669842242201024950551881694803221002515426494639812873677658927688163598312477886520141174110913601164995076629077943646005851941998560162647907615321038727557126992518275687989302761761146162549356495903798045838182323368612016243736569846703785853305275833337939907521660692380533698879565137285593883499894707416181550125397064648171946708348197214488898790676503795903669672494992545279033729636162658976039498576741397359441023744329709355477982629614591442936451428617158587339746791897571211956187385783644758448423555581050025611492391518893099463428413936080383091662818811503715284967059741625628236092168075150177725387402564253470879089137291722828611515915683725241630772254406337875931059826760944203261924285317018781772960235413060672136046000389661093647095141417185777014180606443636815464440053316087783143174440811949422975599314011888683314832802706553833004693290115744147563139997221703804617092894579096271662260740718749975359212756084414737823303270330168237193648002173285734935947564334129943024850235732214597843282641421684878721673367010615094243456984401873312810107945127223737886126058165668053714396127888732527373890392890506865324138062796025930387727697783792868409325365880733988457218746021005311483351323850047827169376218004904795597959290591655470505777514308175112698985188408718564026035305583737832422924185625644255022672155980274012617971928047139600689163828665277009752767069777036439260224372841840883251848770472638440379530166905465937461619323840363893131364327137688841026811219891275223056256756254701725086349765367288605966752740868627407912856576996313789753034660616669804218267724560530660773899624218340859882071864682623215080288286359746839654358856685503773131296587975810501214916207656769950659715344763470320853215603674828608378656803073062657633469774295634643716709397193060876963495328846833613038829431040800296873869117066666146800015121143442256023874474325250769387077775193299942137277211258843608715834835626961661980572526612206797540621062080649882918454395301529982092503005498257043390553570168653120526495614857249257386206917403695213533732531666345466588597286659451136441370331393672118569553952108458407244323835586063106806964924851232632699514603596037297253198368423363904632136710116192821711150282801604488058802382031981493096369596735832742024988245684941273860566491352526706046234450549227581151709314921879592718001940968866986837037302200475314338181092708030017205935530520700706072233999463990571311587099635777359027196285061146514837526209565346713290025994397663114545902685898979115837093419370441155121920117164880566945938131183843765620627846310490346293950029458341164824114969758326011800731699437393506966295712410273239138741754923071862454543222039552735295240245903805744502892246886285336542213815722131163288112052146489805180092024719391710555390113943316681515828843687606961102505171007392762385553386272553538830960671644662370922646809671254061869502143176211668140097595281493907222601112681153108387317617323235263605838173151034595736538223534992935822836851007810884634349983518404451704270189381994243410090575376257767571118090088164183319201962623416288166521374717325477727783488774366518828752156685719506371936565390389449366421764003121527870222366463635755503565576948886549500270853923617105502131147413744106134445544192101336172996285694899193369184729478580729156088510396781959429833186480756083679551496636448965592948187851784038773326247051945050419847742014183947731202815886845707290544057510601285258056594703046836344592652552137008068752009593453607316226118728173928074623094685367823106097921599360019946237993434210687813497346959246469752506246958616909178573976595199392993995567542714654910456860702099012606818704984178079173924071945996323060254707901774527513186809982284730860766536866855516467702911336827563107223346726113705490795365834538637196235856312618387156774118738527722922594743373785695538456246801013905727871016512966636764451872465653730402443684140814488732957847348490003019477888020460324660842875351848364959195082888323206522128104190448047247949291342284951970022601310430062410717971502793433263407995960531446053230488528972917659876016667811937932372453857209607582277178483361613582612896226118129455927462767137794487586753657544861407611931125958512655759734573015333642630767985443385761715333462325270572005303988289499034259566232975782488735029259166825894456894655992658454762694528780516501720674785417887982276806536650641910973434528878338621726156269582654478205672987756426325321594294418039943217000090542650763095588465895171709147607437136893319469090981904501290307099566226620303182649365733698419555776963787624918852865686607600566025605445711337286840205574416030837052312242587223438854123179481388550075689381124935386318635287083799845692619981794523364087429591180747453419551420351726184200845509170845682368200897739455842679214273477560879644279202708312150156406341341617166448069815483764491573900121217041547872591998943825364950514771379399147205219529079396137621107238494290616357604596231253506068537651423115349665683715116604220796394466621163255157729070978473156278277598788136491951257483328793771571459091064841642678309949723674420175862269402159407924480541255360431317992696739157542419296607312393763542139230617876753958711436104089409966089471418340698362993675362621545247298464213752891079884381306095552622720837518629837066787224430195793793786072107254277289071732854874374355781966511716618330881129120245204048682200072344035025448202834254187884653602591506445271657700044521097735585897622655484941621714989532383421600114062950718490427789258552743035221396835679018076406042138307308774460170842688272261177180842664333651780002171903449234264266292261456004337383868335555343453004264818473989215627086095650629340405264943244261445665921291225648893569655009154306426134252668472594914314239398845432486327461842846655985332312210466259890141712103446084271616619001257195870793217569698544013397622096749454185407118446433946990162698351607848924514058940946395267807354579700307051163682519487701189764002827648414160587206184185297189154019688253289309149665345753571427318482016384644832499037886069008072709327673127581966563941148961716832980455139729506687604740915420428429993541025829113502241690769431668574242522509026939034814856451303069925199590436384028429267412573422447765584177886171737265462085498294498946787350929581652632072258992368768457017823038096567883112289305809140572610865884845873101658151167533327674887014829167419701512559782572707406431808601428149024146780472327597684269633935773542930186739439716388611764209004068663398856841681003872389214483176070116684503887212364367043314091155733280182977988736590916659612402021778558854876176161989370794380056663364884365089144805571039765214696027662583599051987042300179465536788 diff --git a/libgo/go/compress/zlib/testdata/pi.txt b/libgo/go/compress/zlib/testdata/pi.txt deleted file mode 100644 index 58d8f3b..0000000 --- a/libgo/go/compress/zlib/testdata/pi.txt +++ /dev/null @@ -1 +0,0 @@ -3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678 diff --git a/libgo/go/container/heap/heap.go b/libgo/go/container/heap/heap.go index 2dfe5b4..ca91139 100644 --- a/libgo/go/container/heap/heap.go +++ b/libgo/go/container/heap/heap.go @@ -11,14 +11,17 @@ import "sort" // Any type that implements heap.Interface may be used as a // min-heap with the following invariants (established after -// Init has been called): +// Init has been called or if the data is empty or sorted): // // !h.Less(j, i) for 0 <= i < h.Len() and j = 2*i+1 or 2*i+2 and j < h.Len() // +// Note that Push and Pop in this interface are for package heap's +// implementation to call. To add and remove things from the heap, +// use heap.Push and heap.Pop. type Interface interface { sort.Interface - Push(x interface{}) - Pop() interface{} + Push(x interface{}) // add x as element Len() + Pop() interface{} // remove and return element Len() - 1. } // A heap must be initialized before any of the heap operations diff --git a/libgo/go/container/heap/heap_test.go b/libgo/go/container/heap/heap_test.go index 6625e3a..cb31ef6 100644 --- a/libgo/go/container/heap/heap_test.go +++ b/libgo/go/container/heap/heap_test.go @@ -5,8 +5,8 @@ package heap_test import ( - "testing" . "container/heap" + "testing" ) type myHeap []int diff --git a/libgo/go/crypto/dsa/dsa.go b/libgo/go/crypto/dsa/dsa.go index 692d62a..a2adc7e 100644 --- a/libgo/go/crypto/dsa/dsa.go +++ b/libgo/go/crypto/dsa/dsa.go @@ -6,9 +6,9 @@ package dsa import ( - "big" "errors" "io" + "math/big" ) // Parameters represents the domain parameters for a key. These parameters can diff --git a/libgo/go/crypto/dsa/dsa_test.go b/libgo/go/crypto/dsa/dsa_test.go index deec08d..177aa44 100644 --- a/libgo/go/crypto/dsa/dsa_test.go +++ b/libgo/go/crypto/dsa/dsa_test.go @@ -5,8 +5,8 @@ package dsa import ( - "big" "crypto/rand" + "math/big" "testing" ) diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go index b7f235b..2f19999 100644 --- a/libgo/go/crypto/ecdsa/ecdsa.go +++ b/libgo/go/crypto/ecdsa/ecdsa.go @@ -13,9 +13,9 @@ package ecdsa // http://www.secg.org/download/aid-780/sec1-v2.pdf import ( - "big" "crypto/elliptic" "io" + "math/big" ) // PublicKey represents an ECDSA public key. diff --git a/libgo/go/crypto/ecdsa/ecdsa_test.go b/libgo/go/crypto/ecdsa/ecdsa_test.go index d6b4039..22360b5 100644 --- a/libgo/go/crypto/ecdsa/ecdsa_test.go +++ b/libgo/go/crypto/ecdsa/ecdsa_test.go @@ -5,11 +5,11 @@ package ecdsa import ( - "big" "crypto/elliptic" - "crypto/sha1" "crypto/rand" + "crypto/sha1" "encoding/hex" + "math/big" "testing" ) diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go index 3c3327f..b7232a2 100644 --- a/libgo/go/crypto/elliptic/elliptic.go +++ b/libgo/go/crypto/elliptic/elliptic.go @@ -14,8 +14,8 @@ package elliptic // reverse the transform than to operate in affine coordinates. import ( - "big" "io" + "math/big" "sync" ) diff --git a/libgo/go/crypto/elliptic/elliptic_test.go b/libgo/go/crypto/elliptic/elliptic_test.go index 9578364..a68a380 100644 --- a/libgo/go/crypto/elliptic/elliptic_test.go +++ b/libgo/go/crypto/elliptic/elliptic_test.go @@ -5,9 +5,9 @@ package elliptic import ( - "big" "crypto/rand" "fmt" + "math/big" "testing" ) diff --git a/libgo/go/crypto/hmac/hmac_test.go b/libgo/go/crypto/hmac/hmac_test.go index bcae63b..03431c9 100644 --- a/libgo/go/crypto/hmac/hmac_test.go +++ b/libgo/go/crypto/hmac/hmac_test.go @@ -5,8 +5,8 @@ package hmac import ( - "hash" "fmt" + "hash" "testing" ) diff --git a/libgo/go/crypto/ocsp/ocsp.go b/libgo/go/crypto/ocsp/ocsp.go index f697fa1..a04b5bd 100644 --- a/libgo/go/crypto/ocsp/ocsp.go +++ b/libgo/go/crypto/ocsp/ocsp.go @@ -8,12 +8,12 @@ package ocsp import ( - "asn1" "crypto" "crypto/rsa" _ "crypto/sha1" "crypto/x509" "crypto/x509/pkix" + "encoding/asn1" "time" ) diff --git a/libgo/go/crypto/openpgp/armor/armor.go b/libgo/go/crypto/openpgp/armor/armor.go index 707bdf3..3bbb5dc 100644 --- a/libgo/go/crypto/openpgp/armor/armor.go +++ b/libgo/go/crypto/openpgp/armor/armor.go @@ -151,7 +151,7 @@ func (r *openpgpReader) Read(p []byte) (n int, err error) { } // Decode reads a PGP armored block from the given Reader. It will ignore -// leading garbage. If it doesn't find a block, it will return nil, os.EOF. The +// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The // given Reader is not usable after calling this function: an arbitrary amount // of data may have been read past the end of the block. func Decode(in io.Reader) (p *Block, err error) { diff --git a/libgo/go/crypto/openpgp/elgamal/elgamal.go b/libgo/go/crypto/openpgp/elgamal/elgamal.go index 2ed49f6..a553bde 100644 --- a/libgo/go/crypto/openpgp/elgamal/elgamal.go +++ b/libgo/go/crypto/openpgp/elgamal/elgamal.go @@ -13,11 +13,11 @@ package elgamal import ( - "big" "crypto/rand" "crypto/subtle" "errors" "io" + "math/big" ) // PublicKey represents an ElGamal public key. diff --git a/libgo/go/crypto/openpgp/elgamal/elgamal_test.go b/libgo/go/crypto/openpgp/elgamal/elgamal_test.go index 101121a..c4f99f5 100644 --- a/libgo/go/crypto/openpgp/elgamal/elgamal_test.go +++ b/libgo/go/crypto/openpgp/elgamal/elgamal_test.go @@ -5,9 +5,9 @@ package elgamal import ( - "big" "bytes" "crypto/rand" + "math/big" "testing" ) diff --git a/libgo/go/crypto/openpgp/packet/encrypted_key.go b/libgo/go/crypto/openpgp/packet/encrypted_key.go index d05103f..b24fa3a 100644 --- a/libgo/go/crypto/openpgp/packet/encrypted_key.go +++ b/libgo/go/crypto/openpgp/packet/encrypted_key.go @@ -5,13 +5,13 @@ package packet import ( - "big" "crypto/openpgp/elgamal" error_ "crypto/openpgp/error" "crypto/rand" "crypto/rsa" "encoding/binary" "io" + "math/big" "strconv" ) diff --git a/libgo/go/crypto/openpgp/packet/encrypted_key_test.go b/libgo/go/crypto/openpgp/packet/encrypted_key_test.go index b402245..2b8eff7 100644 --- a/libgo/go/crypto/openpgp/packet/encrypted_key_test.go +++ b/libgo/go/crypto/openpgp/packet/encrypted_key_test.go @@ -5,11 +5,11 @@ package packet import ( - "big" "bytes" "crypto/rand" "crypto/rsa" "fmt" + "math/big" "testing" ) diff --git a/libgo/go/crypto/openpgp/packet/packet.go b/libgo/go/crypto/openpgp/packet/packet.go index f7ed353..778df15 100644 --- a/libgo/go/crypto/openpgp/packet/packet.go +++ b/libgo/go/crypto/openpgp/packet/packet.go @@ -7,12 +7,12 @@ package packet import ( - "big" "crypto/aes" "crypto/cast5" "crypto/cipher" error_ "crypto/openpgp/error" "io" + "math/big" ) // readFull is the same as io.ReadFull except that reading zero bytes returns diff --git a/libgo/go/crypto/openpgp/packet/private_key.go b/libgo/go/crypto/openpgp/packet/private_key.go index 742ac51..c0ff82b4 100644 --- a/libgo/go/crypto/openpgp/packet/private_key.go +++ b/libgo/go/crypto/openpgp/packet/private_key.go @@ -5,7 +5,6 @@ package packet import ( - "big" "bytes" "crypto/cipher" "crypto/dsa" @@ -16,6 +15,7 @@ import ( "crypto/sha1" "io" "io/ioutil" + "math/big" "strconv" ) diff --git a/libgo/go/crypto/openpgp/packet/public_key.go b/libgo/go/crypto/openpgp/packet/public_key.go index af0bc22..7d71dc4 100644 --- a/libgo/go/crypto/openpgp/packet/public_key.go +++ b/libgo/go/crypto/openpgp/packet/public_key.go @@ -5,7 +5,6 @@ package packet import ( - "big" "crypto/dsa" "crypto/openpgp/elgamal" error_ "crypto/openpgp/error" @@ -15,6 +14,7 @@ import ( "fmt" "hash" "io" + "math/big" "strconv" ) diff --git a/libgo/go/crypto/openpgp/s2k/s2k_test.go b/libgo/go/crypto/openpgp/s2k/s2k_test.go index ec4012c..3a094a1 100644 --- a/libgo/go/crypto/openpgp/s2k/s2k_test.go +++ b/libgo/go/crypto/openpgp/s2k/s2k_test.go @@ -6,8 +6,8 @@ package s2k import ( "bytes" - "crypto/sha1" "crypto/rand" + "crypto/sha1" "encoding/hex" "testing" ) diff --git a/libgo/go/crypto/rand/util.go b/libgo/go/crypto/rand/util.go index 322da4a..b44ae98 100644 --- a/libgo/go/crypto/rand/util.go +++ b/libgo/go/crypto/rand/util.go @@ -5,8 +5,8 @@ package rand import ( - "big" "io" + "math/big" "os" ) diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go index 901539d..d7b053f 100644 --- a/libgo/go/crypto/rsa/pkcs1v15.go +++ b/libgo/go/crypto/rsa/pkcs1v15.go @@ -5,11 +5,11 @@ package rsa import ( - "big" "crypto" "crypto/subtle" "errors" "io" + "math/big" ) // This file implements encryption and decryption using PKCS#1 v1.5 padding. diff --git a/libgo/go/crypto/rsa/pkcs1v15_test.go b/libgo/go/crypto/rsa/pkcs1v15_test.go index d69bacf..66188ac 100644 --- a/libgo/go/crypto/rsa/pkcs1v15_test.go +++ b/libgo/go/crypto/rsa/pkcs1v15_test.go @@ -5,7 +5,6 @@ package rsa import ( - "big" "bytes" "crypto" "crypto/rand" @@ -13,6 +12,7 @@ import ( "encoding/base64" "encoding/hex" "io" + "math/big" "testing" "testing/quick" ) diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go index c9344ff..27ccf61 100644 --- a/libgo/go/crypto/rsa/rsa.go +++ b/libgo/go/crypto/rsa/rsa.go @@ -8,12 +8,12 @@ package rsa // TODO(agl): Add support for PSS padding. import ( - "big" "crypto/rand" "crypto/subtle" "errors" "hash" "io" + "math/big" ) var bigZero = big.NewInt(0) diff --git a/libgo/go/crypto/rsa/rsa_test.go b/libgo/go/crypto/rsa/rsa_test.go index c36bca1..0fb9875 100644 --- a/libgo/go/crypto/rsa/rsa_test.go +++ b/libgo/go/crypto/rsa/rsa_test.go @@ -5,10 +5,10 @@ package rsa import ( - "big" "bytes" "crypto/rand" "crypto/sha1" + "math/big" "testing" ) diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go index 6312c34..f4178e3 100644 --- a/libgo/go/crypto/tls/conn.go +++ b/libgo/go/crypto/tls/conn.go @@ -471,7 +471,7 @@ Again: // RFC suggests that EOF without an alertCloseNotify is // an error, but popular web sites seem to do this, // so we can't make it an error. - // if err == os.EOF { + // if err == io.EOF { // err = io.ErrUnexpectedEOF // } if e, ok := err.(net.Error); !ok || !e.Temporary() { diff --git a/libgo/go/crypto/tls/generate_cert.go b/libgo/go/crypto/tls/generate_cert.go index 41206e2..c4463ff 100644 --- a/libgo/go/crypto/tls/generate_cert.go +++ b/libgo/go/crypto/tls/generate_cert.go @@ -8,14 +8,14 @@ package main import ( - "big" - "crypto/x509/pkix" "crypto/rand" "crypto/rsa" "crypto/x509" + "crypto/x509/pkix" "encoding/pem" "flag" "log" + "math/big" "os" "time" ) diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go index dc68a12..87e8f7e 100644 --- a/libgo/go/crypto/tls/handshake_messages_test.go +++ b/libgo/go/crypto/tls/handshake_messages_test.go @@ -5,7 +5,7 @@ package tls import ( - "rand" + "math/rand" "reflect" "testing" "testing/quick" diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go index f2b0a14..bc37979 100644 --- a/libgo/go/crypto/tls/handshake_server_test.go +++ b/libgo/go/crypto/tls/handshake_server_test.go @@ -5,12 +5,12 @@ package tls import ( - "big" "bytes" "crypto/rsa" "encoding/hex" "flag" "io" + "math/big" "net" "strconv" "strings" diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go index ba34606..08fb852 100644 --- a/libgo/go/crypto/tls/key_agreement.go +++ b/libgo/go/crypto/tls/key_agreement.go @@ -5,7 +5,6 @@ package tls import ( - "big" "crypto" "crypto/elliptic" "crypto/md5" @@ -14,6 +13,7 @@ import ( "crypto/x509" "errors" "io" + "math/big" ) // rsaKeyAgreement implements the standard TLS key agreement where the client diff --git a/libgo/go/crypto/x509/pkcs1.go b/libgo/go/crypto/x509/pkcs1.go index 0d3ade3..31d0dd0 100644 --- a/libgo/go/crypto/x509/pkcs1.go +++ b/libgo/go/crypto/x509/pkcs1.go @@ -5,10 +5,10 @@ package x509 import ( - "asn1" - "big" - "errors" "crypto/rsa" + "encoding/asn1" + "errors" + "math/big" ) // pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key. diff --git a/libgo/go/crypto/x509/pkix/pkix.go b/libgo/go/crypto/x509/pkix/pkix.go index 332a394..b35274c 100644 --- a/libgo/go/crypto/x509/pkix/pkix.go +++ b/libgo/go/crypto/x509/pkix/pkix.go @@ -7,8 +7,8 @@ package pkix import ( - "asn1" - "big" + "encoding/asn1" + "math/big" "time" ) diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go index da8b283..9ff7db9 100644 --- a/libgo/go/crypto/x509/x509.go +++ b/libgo/go/crypto/x509/x509.go @@ -6,17 +6,17 @@ package x509 import ( - "asn1" - "big" "bytes" "crypto" "crypto/dsa" "crypto/rsa" "crypto/sha1" "crypto/x509/pkix" + "encoding/asn1" "encoding/pem" "errors" "io" + "math/big" "time" ) diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go index d113f85..c424715 100644 --- a/libgo/go/crypto/x509/x509_test.go +++ b/libgo/go/crypto/x509/x509_test.go @@ -5,16 +5,16 @@ package x509 import ( - "asn1" - "big" "bytes" "crypto/dsa" "crypto/rand" "crypto/rsa" "crypto/x509/pkix" + "encoding/asn1" "encoding/base64" "encoding/hex" "encoding/pem" + "math/big" "testing" "time" ) diff --git a/libgo/go/csv/reader.go b/libgo/go/csv/reader.go deleted file mode 100644 index ae0f567..0000000 --- a/libgo/go/csv/reader.go +++ /dev/null @@ -1,372 +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 csv reads and writes comma-separated values (CSV) files. -// -// A csv file contains zero or more records of one or more fields per record. -// Each record is separated by the newline character. The final record may -// optionally be followed by a newline character. -// -// field1,field2,field3 -// -// White space is considered part of a field. -// -// Carriage returns before newline characters are silently removed. -// -// Blank lines are ignored. A line with only whitespace characters (excluding -// the ending newline character) is not considered a blank line. -// -// Fields which start and stop with the quote character " are called -// quoted-fields. The beginning and ending quote are not part of the -// field. -// -// The source: -// -// normal string,"quoted-field" -// -// results in the fields -// -// {`normal string`, `quoted-field`} -// -// Within a quoted-field a quote character followed by a second quote -// character is considered a single quote. -// -// "the ""word"" is true","a ""quoted-field""" -// -// results in -// -// {`the "word" is true`, `a "quoted-field"`} -// -// Newlines and commas may be included in a quoted-field -// -// "Multi-line -// field","comma is ," -// -// results in -// -// {`Multi-line -// field`, `comma is ,`} -package csv - -import ( - "bufio" - "bytes" - "errors" - "fmt" - "io" - "unicode" -) - -// A ParseError is returned for parsing errors. -// The first line is 1. The first column is 0. -type ParseError struct { - Line int // Line where the error occurred - Column int // Column (rune index) where the error occurred - Err error // The actual error -} - -func (e *ParseError) Error() string { - return fmt.Sprintf("line %d, column %d: %s", e.Line, e.Column, e.Err) -} - -// These are the errors that can be returned in ParseError.Error -var ( - ErrTrailingComma = errors.New("extra delimiter at end of line") - ErrBareQuote = errors.New("bare \" in non-quoted-field") - ErrQuote = errors.New("extraneous \" in field") - ErrFieldCount = errors.New("wrong number of fields in line") -) - -// A Reader reads records from a CSV-encoded file. -// -// As returned by NewReader, a Reader expects input conforming to RFC 4180. -// The exported fields can be changed to customize the details before the -// first call to Read or ReadAll. -// -// Comma is the field delimiter. It defaults to ','. -// -// Comment, if not 0, is the comment character. Lines beginning with the -// Comment character are ignored. -// -// If FieldsPerRecord is positive, Read requires each record to -// have the given number of fields. If FieldsPerRecord is 0, Read sets it to -// the number of fields in the first record, so that future records must -// have the same field count. -// -// If LazyQuotes is true, a quote may appear in an unquoted field and a -// non-doubled quote may appear in a quoted field. -// -// If TrailingComma is true, the last field may be an unquoted empty field. -// -// If TrimLeadingSpace is true, leading white space in a field is ignored. -type Reader struct { - Comma rune // Field delimiter (set to ',' by NewReader) - Comment rune // Comment character for start of line - FieldsPerRecord int // Number of expected fields per record - LazyQuotes bool // Allow lazy quotes - TrailingComma bool // Allow trailing comma - TrimLeadingSpace bool // Trim leading space - line int - column int - r *bufio.Reader - field bytes.Buffer -} - -// NewReader returns a new Reader that reads from r. -func NewReader(r io.Reader) *Reader { - return &Reader{ - Comma: ',', - r: bufio.NewReader(r), - } -} - -// error creates a new ParseError based on err. -func (r *Reader) error(err error) error { - return &ParseError{ - Line: r.line, - Column: r.column, - Err: err, - } -} - -// Read reads one record from r. The record is a slice of strings with each -// string representing one field. -func (r *Reader) Read() (record []string, err error) { - for { - record, err = r.parseRecord() - if record != nil { - break - } - if err != nil { - return nil, err - } - } - - if r.FieldsPerRecord > 0 { - if len(record) != r.FieldsPerRecord { - r.column = 0 // report at start of record - return record, r.error(ErrFieldCount) - } - } else if r.FieldsPerRecord == 0 { - r.FieldsPerRecord = len(record) - } - return record, nil -} - -// ReadAll reads all the remaining records from r. -// Each record is a slice of fields. -func (r *Reader) ReadAll() (records [][]string, err error) { - for { - record, err := r.Read() - if err == io.EOF { - return records, nil - } - if err != nil { - return nil, err - } - records = append(records, record) - } - panic("unreachable") -} - -// readRune reads one rune from r, folding \r\n to \n and keeping track -// of how far into the line we have read. r.column will point to the start -// of this rune, not the end of this rune. -func (r *Reader) readRune() (rune, error) { - r1, _, err := r.r.ReadRune() - - // Handle \r\n here. We make the simplifying assumption that - // anytime \r is followed by \n that it can be folded to \n. - // We will not detect files which contain both \r\n and bare \n. - if r1 == '\r' { - r1, _, err = r.r.ReadRune() - if err == nil { - if r1 != '\n' { - r.r.UnreadRune() - r1 = '\r' - } - } - } - r.column++ - return r1, err -} - -// unreadRune puts the last rune read from r back. -func (r *Reader) unreadRune() { - r.r.UnreadRune() - r.column-- -} - -// skip reads runes up to and including the rune delim or until error. -func (r *Reader) skip(delim rune) error { - for { - r1, err := r.readRune() - if err != nil { - return err - } - if r1 == delim { - return nil - } - } - panic("unreachable") -} - -// parseRecord reads and parses a single csv record from r. -func (r *Reader) parseRecord() (fields []string, err error) { - // Each record starts on a new line. We increment our line - // number (lines start at 1, not 0) and set column to -1 - // so as we increment in readRune it points to the character we read. - r.line++ - r.column = -1 - - // Peek at the first rune. If it is an error we are done. - // If we are support comments and it is the comment character - // then skip to the end of line. - - r1, _, err := r.r.ReadRune() - if err != nil { - return nil, err - } - - if r.Comment != 0 && r1 == r.Comment { - return nil, r.skip('\n') - } - r.r.UnreadRune() - - // At this point we have at least one field. - for { - haveField, delim, err := r.parseField() - if haveField { - fields = append(fields, r.field.String()) - } - if delim == '\n' || err == io.EOF { - return fields, err - } else if err != nil { - return nil, err - } - } - panic("unreachable") -} - -// parseField parses the next field in the record. The read field is -// located in r.field. Delim is the first character not part of the field -// (r.Comma or '\n'). -func (r *Reader) parseField() (haveField bool, delim rune, err error) { - r.field.Reset() - - r1, err := r.readRune() - if err != nil { - // If we have EOF and are not at the start of a line - // then we return the empty field. We have already - // checked for trailing commas if needed. - if err == io.EOF && r.column != 0 { - return true, 0, err - } - return false, 0, err - } - - if r.TrimLeadingSpace { - for r1 != '\n' && unicode.IsSpace(r1) { - r1, err = r.readRune() - if err != nil { - return false, 0, err - } - } - } - - switch r1 { - case r.Comma: - // will check below - - case '\n': - // We are a trailing empty field or a blank line - if r.column == 0 { - return false, r1, nil - } - return true, r1, nil - - case '"': - // quoted field - Quoted: - for { - r1, err = r.readRune() - if err != nil { - if err == io.EOF { - if r.LazyQuotes { - return true, 0, err - } - return false, 0, r.error(ErrQuote) - } - return false, 0, err - } - switch r1 { - case '"': - r1, err = r.readRune() - if err != nil || r1 == r.Comma { - break Quoted - } - if r1 == '\n' { - return true, r1, nil - } - if r1 != '"' { - if !r.LazyQuotes { - r.column-- - return false, 0, r.error(ErrQuote) - } - // accept the bare quote - r.field.WriteRune('"') - } - case '\n': - r.line++ - r.column = -1 - } - r.field.WriteRune(r1) - } - - default: - // unquoted field - for { - r.field.WriteRune(r1) - r1, err = r.readRune() - if err != nil || r1 == r.Comma { - break - } - if r1 == '\n' { - return true, r1, nil - } - if !r.LazyQuotes && r1 == '"' { - return false, 0, r.error(ErrBareQuote) - } - } - } - - if err != nil { - if err == io.EOF { - return true, 0, err - } - return false, 0, err - } - - if !r.TrailingComma { - // We don't allow trailing commas. See if we - // are at the end of the line (being mindful - // of trimming spaces). - c := r.column - r1, err = r.readRune() - if r.TrimLeadingSpace { - for r1 != '\n' && unicode.IsSpace(r1) { - r1, err = r.readRune() - if err != nil { - break - } - } - } - if err == io.EOF || r1 == '\n' { - r.column = c // report the comma - return false, 0, r.error(ErrTrailingComma) - } - r.unreadRune() - } - return true, r1, nil -} diff --git a/libgo/go/csv/reader_test.go b/libgo/go/csv/reader_test.go deleted file mode 100644 index 5fd84a7..0000000 --- a/libgo/go/csv/reader_test.go +++ /dev/null @@ -1,281 +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 csv - -import ( - "reflect" - "strings" - "testing" -) - -var readTests = []struct { - Name string - Input string - Output [][]string - UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1 - - // These fields are copied into the Reader - Comma rune - Comment rune - FieldsPerRecord int - LazyQuotes bool - TrailingComma bool - TrimLeadingSpace bool - - Error string - Line int // Expected error line if != 0 - Column int // Expected error column if line != 0 -}{ - { - Name: "Simple", - Input: "a,b,c\n", - Output: [][]string{{"a", "b", "c"}}, - }, - { - Name: "CRLF", - Input: "a,b\r\nc,d\r\n", - Output: [][]string{{"a", "b"}, {"c", "d"}}, - }, - { - Name: "BareCR", - Input: "a,b\rc,d\r\n", - Output: [][]string{{"a", "b\rc", "d"}}, - }, - { - Name: "RFC4180test", - UseFieldsPerRecord: true, - Input: `#field1,field2,field3 -"aaa","bb -b","ccc" -"a,a","b""bb","ccc" -zzz,yyy,xxx -`, - Output: [][]string{ - {"#field1", "field2", "field3"}, - {"aaa", "bb\nb", "ccc"}, - {"a,a", `b"bb`, "ccc"}, - {"zzz", "yyy", "xxx"}, - }, - }, - { - Name: "NoEOLTest", - Input: "a,b,c", - Output: [][]string{{"a", "b", "c"}}, - }, - { - Name: "Semicolon", - Comma: ';', - Input: "a;b;c\n", - Output: [][]string{{"a", "b", "c"}}, - }, - { - Name: "MultiLine", - Input: `"two -line","one line","three -line -field"`, - Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}}, - }, - { - Name: "BlankLine", - Input: "a,b,c\n\nd,e,f\n\n", - Output: [][]string{ - {"a", "b", "c"}, - {"d", "e", "f"}, - }, - }, - { - Name: "TrimSpace", - Input: " a, b, c\n", - TrimLeadingSpace: true, - Output: [][]string{{"a", "b", "c"}}, - }, - { - Name: "LeadingSpace", - Input: " a, b, c\n", - Output: [][]string{{" a", " b", " c"}}, - }, - { - Name: "Comment", - Comment: '#', - Input: "#1,2,3\na,b,c\n#comment", - Output: [][]string{{"a", "b", "c"}}, - }, - { - Name: "NoComment", - Input: "#1,2,3\na,b,c", - Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}}, - }, - { - Name: "LazyQuotes", - LazyQuotes: true, - Input: `a "word","1"2",a","b`, - Output: [][]string{{`a "word"`, `1"2`, `a"`, `b`}}, - }, - { - Name: "BareQuotes", - LazyQuotes: true, - Input: `a "word","1"2",a"`, - Output: [][]string{{`a "word"`, `1"2`, `a"`}}, - }, - { - Name: "BareDoubleQuotes", - LazyQuotes: true, - Input: `a""b,c`, - Output: [][]string{{`a""b`, `c`}}, - }, - { - Name: "BadDoubleQuotes", - Input: `a""b,c`, - Error: `bare " in non-quoted-field`, Line: 1, Column: 1, - }, - { - Name: "TrimQuote", - Input: ` "a"," b",c`, - TrimLeadingSpace: true, - Output: [][]string{{"a", " b", "c"}}, - }, - { - Name: "BadBareQuote", - Input: `a "word","b"`, - Error: `bare " in non-quoted-field`, Line: 1, Column: 2, - }, - { - Name: "BadTrailingQuote", - Input: `"a word",b"`, - Error: `bare " in non-quoted-field`, Line: 1, Column: 10, - }, - { - Name: "ExtraneousQuote", - Input: `"a "word","b"`, - Error: `extraneous " in field`, Line: 1, Column: 3, - }, - { - Name: "BadFieldCount", - UseFieldsPerRecord: true, - Input: "a,b,c\nd,e", - Error: "wrong number of fields", Line: 2, - }, - { - Name: "BadFieldCount1", - UseFieldsPerRecord: true, - FieldsPerRecord: 2, - Input: `a,b,c`, - Error: "wrong number of fields", Line: 1, - }, - { - Name: "FieldCount", - Input: "a,b,c\nd,e", - Output: [][]string{{"a", "b", "c"}, {"d", "e"}}, - }, - { - Name: "BadTrailingCommaEOF", - Input: "a,b,c,", - Error: "extra delimiter at end of line", Line: 1, Column: 5, - }, - { - Name: "BadTrailingCommaEOL", - Input: "a,b,c,\n", - Error: "extra delimiter at end of line", Line: 1, Column: 5, - }, - { - Name: "BadTrailingCommaSpaceEOF", - TrimLeadingSpace: true, - Input: "a,b,c, ", - Error: "extra delimiter at end of line", Line: 1, Column: 5, - }, - { - Name: "BadTrailingCommaSpaceEOL", - TrimLeadingSpace: true, - Input: "a,b,c, \n", - Error: "extra delimiter at end of line", Line: 1, Column: 5, - }, - { - Name: "BadTrailingCommaLine3", - TrimLeadingSpace: true, - Input: "a,b,c\nd,e,f\ng,hi,", - Error: "extra delimiter at end of line", Line: 3, Column: 4, - }, - { - Name: "NotTrailingComma3", - Input: "a,b,c, \n", - Output: [][]string{{"a", "b", "c", " "}}, - }, - { - Name: "CommaFieldTest", - TrailingComma: true, - Input: `x,y,z,w -x,y,z, -x,y,, -x,,, -,,, -"x","y","z","w" -"x","y","z","" -"x","y","","" -"x","","","" -"","","","" -`, - Output: [][]string{ - {"x", "y", "z", "w"}, - {"x", "y", "z", ""}, - {"x", "y", "", ""}, - {"x", "", "", ""}, - {"", "", "", ""}, - {"x", "y", "z", "w"}, - {"x", "y", "z", ""}, - {"x", "y", "", ""}, - {"x", "", "", ""}, - {"", "", "", ""}, - }, - }, - { - Name: "Issue 2366", - TrailingComma: true, - TrimLeadingSpace: true, - Input: "a,b,\nc,d,e", - Output: [][]string{ - {"a", "b", ""}, - {"c", "d", "e"}, - }, - }, - { - Name: "Issue 2366a", - TrailingComma: false, - TrimLeadingSpace: true, - Input: "a,b,\nc,d,e", - Error: "extra delimiter at end of line", - }, -} - -func TestRead(t *testing.T) { - for _, tt := range readTests { - r := NewReader(strings.NewReader(tt.Input)) - r.Comment = tt.Comment - if tt.UseFieldsPerRecord { - r.FieldsPerRecord = tt.FieldsPerRecord - } else { - r.FieldsPerRecord = -1 - } - r.LazyQuotes = tt.LazyQuotes - r.TrailingComma = tt.TrailingComma - r.TrimLeadingSpace = tt.TrimLeadingSpace - if tt.Comma != 0 { - r.Comma = tt.Comma - } - out, err := r.ReadAll() - perr, _ := err.(*ParseError) - if tt.Error != "" { - if err == nil || !strings.Contains(err.Error(), tt.Error) { - t.Errorf("%s: error %v, want error %q", tt.Name, err, tt.Error) - } else if tt.Line != 0 && (tt.Line != perr.Line || tt.Column != perr.Column) { - t.Errorf("%s: error at %d:%d expected %d:%d", tt.Name, perr.Line, perr.Column, tt.Line, tt.Column) - } - } else if err != nil { - t.Errorf("%s: unexpected error %v", tt.Name, err) - } else if !reflect.DeepEqual(out, tt.Output) { - t.Errorf("%s: out=%q want %q", tt.Name, out, tt.Output) - } - } -} diff --git a/libgo/go/csv/writer.go b/libgo/go/csv/writer.go deleted file mode 100644 index 5ea20e1..0000000 --- a/libgo/go/csv/writer.go +++ /dev/null @@ -1,121 +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 csv - -import ( - "bufio" - "io" - "strings" - "unicode" - "utf8" -) - -// A Writer writes records to a CSV encoded file. -// -// As returned by NewWriter, a Writer writes records terminated by a -// newline and uses ',' as the field delimiter. The exported fields can be -// changed to customize the details before the first call to Write or WriteAll. -// -// Comma is the field delimiter. -// -// If UseCRLF is true, the Writer ends each record with \r\n instead of \n. -type Writer struct { - Comma rune // Field delimiter (set to to ',' by NewWriter) - UseCRLF bool // True to use \r\n as the line terminator - w *bufio.Writer -} - -// NewWriter returns a new Writer that writes to w. -func NewWriter(w io.Writer) *Writer { - return &Writer{ - Comma: ',', - w: bufio.NewWriter(w), - } -} - -// Writer writes a single CSV record to w along with any necessary quoting. -// A record is a slice of strings with each string being one field. -func (w *Writer) Write(record []string) (err error) { - for n, field := range record { - if n > 0 { - if _, err = w.w.WriteRune(w.Comma); err != nil { - return - } - } - - // If we don't have to have a quoted field then just - // write out the field and continue to the next field. - if !w.fieldNeedsQuotes(field) { - if _, err = w.w.WriteString(field); err != nil { - return - } - continue - } - if err = w.w.WriteByte('"'); err != nil { - return - } - - for _, r1 := range field { - switch r1 { - case '"': - _, err = w.w.WriteString(`""`) - case '\r': - if !w.UseCRLF { - err = w.w.WriteByte('\r') - } - case '\n': - if w.UseCRLF { - _, err = w.w.WriteString("\r\n") - } else { - err = w.w.WriteByte('\n') - } - default: - _, err = w.w.WriteRune(r1) - } - if err != nil { - return - } - } - - if err = w.w.WriteByte('"'); err != nil { - return - } - } - if w.UseCRLF { - _, err = w.w.WriteString("\r\n") - } else { - err = w.w.WriteByte('\n') - } - return -} - -// Flush writes any buffered data to the underlying io.Writer. -func (w *Writer) Flush() { - w.w.Flush() -} - -// WriteAll writes multiple CSV records to w using Write and then calls Flush. -func (w *Writer) WriteAll(records [][]string) (err error) { - for _, record := range records { - err = w.Write(record) - if err != nil { - break - } - } - w.Flush() - return nil -} - -// fieldNeedsQuotes returns true if our field must be enclosed in quotes. -// Empty fields, files with a Comma, fields with a quote or newline, and -// fields which start with a space must be enclosed in quotes. -func (w *Writer) fieldNeedsQuotes(field string) bool { - if len(field) == 0 || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 { - return true - } - - r1, _ := utf8.DecodeRuneInString(field) - return unicode.IsSpace(r1) -} diff --git a/libgo/go/csv/writer_test.go b/libgo/go/csv/writer_test.go deleted file mode 100644 index 5789590..0000000 --- a/libgo/go/csv/writer_test.go +++ /dev/null @@ -1,44 +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 csv - -import ( - "bytes" - "testing" -) - -var writeTests = []struct { - Input [][]string - Output string - UseCRLF bool -}{ - {Input: [][]string{{"abc"}}, Output: "abc\n"}, - {Input: [][]string{{"abc"}}, Output: "abc\r\n", UseCRLF: true}, - {Input: [][]string{{`"abc"`}}, Output: `"""abc"""` + "\n"}, - {Input: [][]string{{`a"b`}}, Output: `"a""b"` + "\n"}, - {Input: [][]string{{`"a"b"`}}, Output: `"""a""b"""` + "\n"}, - {Input: [][]string{{" abc"}}, Output: `" abc"` + "\n"}, - {Input: [][]string{{"abc,def"}}, Output: `"abc,def"` + "\n"}, - {Input: [][]string{{"abc", "def"}}, Output: "abc,def\n"}, - {Input: [][]string{{"abc"}, {"def"}}, Output: "abc\ndef\n"}, - {Input: [][]string{{"abc\ndef"}}, Output: "\"abc\ndef\"\n"}, - {Input: [][]string{{"abc\ndef"}}, Output: "\"abc\r\ndef\"\r\n", UseCRLF: true}, -} - -func TestWrite(t *testing.T) { - for n, tt := range writeTests { - b := &bytes.Buffer{} - f := NewWriter(b) - f.UseCRLF = tt.UseCRLF - err := f.WriteAll(tt.Input) - if err != nil { - t.Errorf("Unexpected error: %s\n", err) - } - out := b.String() - if out != tt.Output { - t.Errorf("#%d: out=%q want %q", n, out, tt.Output) - } - } -} diff --git a/libgo/go/debug/gosym/pclntab_test.go b/libgo/go/debug/gosym/pclntab_test.go index c83e64e..562e7a0 100644 --- a/libgo/go/debug/gosym/pclntab_test.go +++ b/libgo/go/debug/gosym/pclntab_test.go @@ -7,8 +7,8 @@ package gosym import ( "debug/elf" "os" - "testing" "syscall" + "testing" ) func dotest() bool { diff --git a/libgo/go/encoding/asn1/asn1.go b/libgo/go/encoding/asn1/asn1.go new file mode 100644 index 0000000..a006665 --- /dev/null +++ b/libgo/go/encoding/asn1/asn1.go @@ -0,0 +1,841 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package asn1 implements parsing of DER-encoded ASN.1 data structures, +// as defined in ITU-T Rec X.690. +// +// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,'' +// http://luca.ntop.org/Teaching/Appunti/asn1.html. +package asn1 + +// ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc +// are different encoding formats for those objects. Here, we'll be dealing +// with DER, the Distinguished Encoding Rules. DER is used in X.509 because +// it's fast to parse and, unlike BER, has a unique encoding for every object. +// When calculating hashes over objects, it's important that the resulting +// bytes be the same at both ends and DER removes this margin of error. +// +// ASN.1 is very complex and this package doesn't attempt to implement +// everything by any means. + +import ( + "fmt" + "math/big" + "reflect" + "time" +) + +// A StructuralError suggests that the ASN.1 data is valid, but the Go type +// which is receiving it doesn't match. +type StructuralError struct { + Msg string +} + +func (e StructuralError) Error() string { return "ASN.1 structure error: " + e.Msg } + +// A SyntaxError suggests that the ASN.1 data is invalid. +type SyntaxError struct { + Msg string +} + +func (e SyntaxError) Error() string { return "ASN.1 syntax error: " + e.Msg } + +// We start by dealing with each of the primitive types in turn. + +// BOOLEAN + +func parseBool(bytes []byte) (ret bool, err error) { + if len(bytes) != 1 { + err = SyntaxError{"invalid boolean"} + return + } + + return bytes[0] != 0, nil +} + +// INTEGER + +// parseInt64 treats the given bytes as a big-endian, signed integer and +// returns the result. +func parseInt64(bytes []byte) (ret int64, err error) { + if len(bytes) > 8 { + // We'll overflow an int64 in this case. + err = StructuralError{"integer too large"} + return + } + for bytesRead := 0; bytesRead < len(bytes); bytesRead++ { + ret <<= 8 + ret |= int64(bytes[bytesRead]) + } + + // Shift up and down in order to sign extend the result. + ret <<= 64 - uint8(len(bytes))*8 + ret >>= 64 - uint8(len(bytes))*8 + return +} + +// parseInt treats the given bytes as a big-endian, signed integer and returns +// the result. +func parseInt(bytes []byte) (int, error) { + ret64, err := parseInt64(bytes) + if err != nil { + return 0, err + } + if ret64 != int64(int(ret64)) { + return 0, StructuralError{"integer too large"} + } + return int(ret64), nil +} + +var bigOne = big.NewInt(1) + +// parseBigInt treats the given bytes as a big-endian, signed integer and returns +// the result. +func parseBigInt(bytes []byte) *big.Int { + ret := new(big.Int) + if len(bytes) > 0 && bytes[0]&0x80 == 0x80 { + // This is a negative number. + notBytes := make([]byte, len(bytes)) + for i := range notBytes { + notBytes[i] = ^bytes[i] + } + ret.SetBytes(notBytes) + ret.Add(ret, bigOne) + ret.Neg(ret) + return ret + } + ret.SetBytes(bytes) + return ret +} + +// BIT STRING + +// BitString is the structure to use when you want an ASN.1 BIT STRING type. A +// bit string is padded up to the nearest byte in memory and the number of +// valid bits is recorded. Padding bits will be zero. +type BitString struct { + Bytes []byte // bits packed into bytes. + BitLength int // length in bits. +} + +// At returns the bit at the given index. If the index is out of range it +// returns false. +func (b BitString) At(i int) int { + if i < 0 || i >= b.BitLength { + return 0 + } + x := i / 8 + y := 7 - uint(i%8) + return int(b.Bytes[x]>>y) & 1 +} + +// RightAlign returns a slice where the padding bits are at the beginning. The +// slice may share memory with the BitString. +func (b BitString) RightAlign() []byte { + shift := uint(8 - (b.BitLength % 8)) + if shift == 8 || len(b.Bytes) == 0 { + return b.Bytes + } + + a := make([]byte, len(b.Bytes)) + a[0] = b.Bytes[0] >> shift + for i := 1; i < len(b.Bytes); i++ { + a[i] = b.Bytes[i-1] << (8 - shift) + a[i] |= b.Bytes[i] >> shift + } + + return a +} + +// parseBitString parses an ASN.1 bit string from the given byte slice and returns it. +func parseBitString(bytes []byte) (ret BitString, err error) { + if len(bytes) == 0 { + err = SyntaxError{"zero length BIT STRING"} + return + } + paddingBits := int(bytes[0]) + if paddingBits > 7 || + len(bytes) == 1 && paddingBits > 0 || + bytes[len(bytes)-1]&((1< 4 { + err = StructuralError{"base 128 integer too large"} + return + } + ret <<= 7 + b := bytes[offset] + ret |= int(b & 0x7f) + offset++ + if b&0x80 == 0 { + return + } + } + err = SyntaxError{"truncated base 128 integer"} + return +} + +// UTCTime + +func parseUTCTime(bytes []byte) (ret *time.Time, err error) { + s := string(bytes) + ret, err = time.Parse("0601021504Z0700", s) + if err == nil { + return + } + ret, err = time.Parse("060102150405Z0700", s) + return +} + +// parseGeneralizedTime parses the GeneralizedTime from the given byte slice +// and returns the resulting time. +func parseGeneralizedTime(bytes []byte) (ret *time.Time, err error) { + return time.Parse("20060102150405Z0700", string(bytes)) +} + +// PrintableString + +// parsePrintableString parses a ASN.1 PrintableString from the given byte +// array and returns it. +func parsePrintableString(bytes []byte) (ret string, err error) { + for _, b := range bytes { + if !isPrintable(b) { + err = SyntaxError{"PrintableString contains invalid character"} + return + } + } + ret = string(bytes) + return +} + +// isPrintable returns true iff the given b is in the ASN.1 PrintableString set. +func isPrintable(b byte) bool { + return 'a' <= b && b <= 'z' || + 'A' <= b && b <= 'Z' || + '0' <= b && b <= '9' || + '\'' <= b && b <= ')' || + '+' <= b && b <= '/' || + b == ' ' || + b == ':' || + b == '=' || + b == '?' || + // This is technically not allowed in a PrintableString. + // However, x509 certificates with wildcard strings don't + // always use the correct string type so we permit it. + b == '*' +} + +// IA5String + +// parseIA5String parses a ASN.1 IA5String (ASCII string) from the given +// byte slice and returns it. +func parseIA5String(bytes []byte) (ret string, err error) { + for _, b := range bytes { + if b >= 0x80 { + err = SyntaxError{"IA5String contains invalid character"} + return + } + } + ret = string(bytes) + return +} + +// T61String + +// parseT61String parses a ASN.1 T61String (8-bit clean string) from the given +// byte slice and returns it. +func parseT61String(bytes []byte) (ret string, err error) { + return string(bytes), nil +} + +// UTF8String + +// parseUTF8String parses a ASN.1 UTF8String (raw UTF-8) from the given byte +// array and returns it. +func parseUTF8String(bytes []byte) (ret string, err error) { + return string(bytes), nil +} + +// A RawValue represents an undecoded ASN.1 object. +type RawValue struct { + Class, Tag int + IsCompound bool + Bytes []byte + FullBytes []byte // includes the tag and length +} + +// RawContent is used to signal that the undecoded, DER data needs to be +// preserved for a struct. To use it, the first field of the struct must have +// this type. It's an error for any of the other fields to have this type. +type RawContent []byte + +// Tagging + +// parseTagAndLength parses an ASN.1 tag and length pair from the given offset +// into a byte slice. It returns the parsed data and the new offset. SET and +// SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we +// don't distinguish between ordered and unordered objects in this code. +func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) { + offset = initOffset + b := bytes[offset] + offset++ + ret.class = int(b >> 6) + ret.isCompound = b&0x20 == 0x20 + ret.tag = int(b & 0x1f) + + // If the bottom five bits are set, then the tag number is actually base 128 + // encoded afterwards + if ret.tag == 0x1f { + ret.tag, offset, err = parseBase128Int(bytes, offset) + if err != nil { + return + } + } + if offset >= len(bytes) { + err = SyntaxError{"truncated tag or length"} + return + } + b = bytes[offset] + offset++ + if b&0x80 == 0 { + // The length is encoded in the bottom 7 bits. + ret.length = int(b & 0x7f) + } else { + // Bottom 7 bits give the number of length bytes to follow. + numBytes := int(b & 0x7f) + // We risk overflowing a signed 32-bit number if we accept more than 3 bytes. + if numBytes > 3 { + err = StructuralError{"length too large"} + return + } + if numBytes == 0 { + err = SyntaxError{"indefinite length found (not DER)"} + return + } + ret.length = 0 + for i := 0; i < numBytes; i++ { + if offset >= len(bytes) { + err = SyntaxError{"truncated tag or length"} + return + } + b = bytes[offset] + offset++ + ret.length <<= 8 + ret.length |= int(b) + } + } + + return +} + +// parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse +// a number of ASN.1 values from the given byte slice and returns them as a +// slice of Go values of the given type. +func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err error) { + expectedTag, compoundType, ok := getUniversalType(elemType) + if !ok { + err = StructuralError{"unknown Go type for slice"} + return + } + + // First we iterate over the input and count the number of elements, + // checking that the types are correct in each case. + numElements := 0 + for offset := 0; offset < len(bytes); { + var t tagAndLength + t, offset, err = parseTagAndLength(bytes, offset) + if err != nil { + return + } + // We pretend that GENERAL STRINGs are PRINTABLE STRINGs so + // that a sequence of them can be parsed into a []string. + if t.tag == tagGeneralString { + t.tag = tagPrintableString + } + if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag { + err = StructuralError{"sequence tag mismatch"} + return + } + if invalidLength(offset, t.length, len(bytes)) { + err = SyntaxError{"truncated sequence"} + return + } + offset += t.length + numElements++ + } + ret = reflect.MakeSlice(sliceType, numElements, numElements) + params := fieldParameters{} + offset := 0 + for i := 0; i < numElements; i++ { + offset, err = parseField(ret.Index(i), bytes, offset, params) + if err != nil { + return + } + } + return +} + +var ( + bitStringType = reflect.TypeOf(BitString{}) + objectIdentifierType = reflect.TypeOf(ObjectIdentifier{}) + enumeratedType = reflect.TypeOf(Enumerated(0)) + flagType = reflect.TypeOf(Flag(false)) + timeType = reflect.TypeOf(&time.Time{}) + rawValueType = reflect.TypeOf(RawValue{}) + rawContentsType = reflect.TypeOf(RawContent(nil)) + bigIntType = reflect.TypeOf(new(big.Int)) +) + +// invalidLength returns true iff offset + length > sliceLength, or if the +// addition would overflow. +func invalidLength(offset, length, sliceLength int) bool { + return offset+length < offset || offset+length > sliceLength +} + +// parseField is the main parsing function. Given a byte slice and an offset +// into the array, it will try to parse a suitable ASN.1 value out and store it +// in the given Value. +func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err error) { + offset = initOffset + fieldType := v.Type() + + // If we have run out of data, it may be that there are optional elements at the end. + if offset == len(bytes) { + if !setDefaultValue(v, params) { + err = SyntaxError{"sequence truncated"} + } + return + } + + // Deal with raw values. + if fieldType == rawValueType { + var t tagAndLength + t, offset, err = parseTagAndLength(bytes, offset) + if err != nil { + return + } + if invalidLength(offset, t.length, len(bytes)) { + err = SyntaxError{"data truncated"} + return + } + result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]} + offset += t.length + v.Set(reflect.ValueOf(result)) + return + } + + // Deal with the ANY type. + if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 { + var t tagAndLength + t, offset, err = parseTagAndLength(bytes, offset) + if err != nil { + return + } + if invalidLength(offset, t.length, len(bytes)) { + err = SyntaxError{"data truncated"} + return + } + var result interface{} + if !t.isCompound && t.class == classUniversal { + innerBytes := bytes[offset : offset+t.length] + switch t.tag { + case tagPrintableString: + result, err = parsePrintableString(innerBytes) + case tagIA5String: + result, err = parseIA5String(innerBytes) + case tagT61String: + result, err = parseT61String(innerBytes) + case tagUTF8String: + result, err = parseUTF8String(innerBytes) + case tagInteger: + result, err = parseInt64(innerBytes) + case tagBitString: + result, err = parseBitString(innerBytes) + case tagOID: + result, err = parseObjectIdentifier(innerBytes) + case tagUTCTime: + result, err = parseUTCTime(innerBytes) + case tagOctetString: + result = innerBytes + default: + // If we don't know how to handle the type, we just leave Value as nil. + } + } + offset += t.length + if err != nil { + return + } + if result != nil { + v.Set(reflect.ValueOf(result)) + } + return + } + universalTag, compoundType, ok1 := getUniversalType(fieldType) + if !ok1 { + err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)} + return + } + + t, offset, err := parseTagAndLength(bytes, offset) + if err != nil { + return + } + if params.explicit { + expectedClass := classContextSpecific + if params.application { + expectedClass = classApplication + } + if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) { + if t.length > 0 { + t, offset, err = parseTagAndLength(bytes, offset) + if err != nil { + return + } + } else { + if fieldType != flagType { + err = StructuralError{"Zero length explicit tag was not an asn1.Flag"} + return + } + v.SetBool(true) + return + } + } else { + // The tags didn't match, it might be an optional element. + ok := setDefaultValue(v, params) + if ok { + offset = initOffset + } else { + err = StructuralError{"explicitly tagged member didn't match"} + } + return + } + } + + // Special case for strings: all the ASN.1 string types map to the Go + // type string. getUniversalType returns the tag for PrintableString + // when it sees a string, so if we see a different string type on the + // wire, we change the universal type to match. + if universalTag == tagPrintableString { + switch t.tag { + case tagIA5String, tagGeneralString, tagT61String, tagUTF8String: + universalTag = t.tag + } + } + + // Special case for time: UTCTime and GeneralizedTime both map to the + // Go type time.Time. + if universalTag == tagUTCTime && t.tag == tagGeneralizedTime { + universalTag = tagGeneralizedTime + } + + expectedClass := classUniversal + expectedTag := universalTag + + if !params.explicit && params.tag != nil { + expectedClass = classContextSpecific + expectedTag = *params.tag + } + + if !params.explicit && params.application && params.tag != nil { + expectedClass = classApplication + expectedTag = *params.tag + } + + // We have unwrapped any explicit tagging at this point. + if t.class != expectedClass || t.tag != expectedTag || t.isCompound != compoundType { + // Tags don't match. Again, it could be an optional element. + ok := setDefaultValue(v, params) + if ok { + offset = initOffset + } else { + err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)} + } + return + } + if invalidLength(offset, t.length, len(bytes)) { + err = SyntaxError{"data truncated"} + return + } + innerBytes := bytes[offset : offset+t.length] + offset += t.length + + // We deal with the structures defined in this package first. + switch fieldType { + case objectIdentifierType: + newSlice, err1 := parseObjectIdentifier(innerBytes) + v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice))) + if err1 == nil { + reflect.Copy(v, reflect.ValueOf(newSlice)) + } + err = err1 + return + case bitStringType: + bs, err1 := parseBitString(innerBytes) + if err1 == nil { + v.Set(reflect.ValueOf(bs)) + } + err = err1 + return + case timeType: + var time *time.Time + var err1 error + if universalTag == tagUTCTime { + time, err1 = parseUTCTime(innerBytes) + } else { + time, err1 = parseGeneralizedTime(innerBytes) + } + if err1 == nil { + v.Set(reflect.ValueOf(time)) + } + err = err1 + return + case enumeratedType: + parsedInt, err1 := parseInt(innerBytes) + if err1 == nil { + v.SetInt(int64(parsedInt)) + } + err = err1 + return + case flagType: + v.SetBool(true) + return + case bigIntType: + parsedInt := parseBigInt(innerBytes) + v.Set(reflect.ValueOf(parsedInt)) + return + } + switch val := v; val.Kind() { + case reflect.Bool: + parsedBool, err1 := parseBool(innerBytes) + if err1 == nil { + val.SetBool(parsedBool) + } + err = err1 + return + case reflect.Int, reflect.Int32: + parsedInt, err1 := parseInt(innerBytes) + if err1 == nil { + val.SetInt(int64(parsedInt)) + } + err = err1 + return + case reflect.Int64: + parsedInt, err1 := parseInt64(innerBytes) + if err1 == nil { + val.SetInt(parsedInt) + } + err = err1 + return + // TODO(dfc) Add support for the remaining integer types + case reflect.Struct: + structType := fieldType + + if structType.NumField() > 0 && + structType.Field(0).Type == rawContentsType { + bytes := bytes[initOffset:offset] + val.Field(0).Set(reflect.ValueOf(RawContent(bytes))) + } + + innerOffset := 0 + for i := 0; i < structType.NumField(); i++ { + field := structType.Field(i) + if i == 0 && field.Type == rawContentsType { + continue + } + innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1"))) + if err != nil { + return + } + } + // We allow extra bytes at the end of the SEQUENCE because + // adding elements to the end has been used in X.509 as the + // version numbers have increased. + return + case reflect.Slice: + sliceType := fieldType + if sliceType.Elem().Kind() == reflect.Uint8 { + val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes))) + reflect.Copy(val, reflect.ValueOf(innerBytes)) + return + } + newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem()) + if err1 == nil { + val.Set(newSlice) + } + err = err1 + return + case reflect.String: + var v string + switch universalTag { + case tagPrintableString: + v, err = parsePrintableString(innerBytes) + case tagIA5String: + v, err = parseIA5String(innerBytes) + case tagT61String: + v, err = parseT61String(innerBytes) + case tagUTF8String: + v, err = parseUTF8String(innerBytes) + case tagGeneralString: + // GeneralString is specified in ISO-2022/ECMA-35, + // A brief review suggests that it includes structures + // that allow the encoding to change midstring and + // such. We give up and pass it as an 8-bit string. + v, err = parseT61String(innerBytes) + default: + err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)} + } + if err == nil { + val.SetString(v) + } + return + } + err = StructuralError{"unsupported: " + v.Type().String()} + return +} + +// setDefaultValue is used to install a default value, from a tag string, into +// a Value. It is successful is the field was optional, even if a default value +// wasn't provided or it failed to install it into the Value. +func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { + if !params.optional { + return + } + ok = true + if params.defaultValue == nil { + return + } + switch val := v; val.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + val.SetInt(*params.defaultValue) + } + return +} + +// Unmarshal parses the DER-encoded ASN.1 data structure b +// and uses the reflect package to fill in an arbitrary value pointed at by val. +// Because Unmarshal uses the reflect package, the structs +// being written to must use upper case field names. +// +// An ASN.1 INTEGER can be written to an int, int32 or int64. +// If the encoded value does not fit in the Go type, +// Unmarshal returns a parse error. +// +// An ASN.1 BIT STRING can be written to a BitString. +// +// An ASN.1 OCTET STRING can be written to a []byte. +// +// An ASN.1 OBJECT IDENTIFIER can be written to an +// ObjectIdentifier. +// +// An ASN.1 ENUMERATED can be written to an Enumerated. +// +// An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a *time.Time. +// +// An ASN.1 PrintableString or IA5String can be written to a string. +// +// Any of the above ASN.1 values can be written to an interface{}. +// The value stored in the interface has the corresponding Go type. +// For integers, that type is int64. +// +// An ASN.1 SEQUENCE OF x or SET OF x can be written +// to a slice if an x can be written to the slice's element type. +// +// An ASN.1 SEQUENCE or SET can be written to a struct +// if each of the elements in the sequence can be +// written to the corresponding element in the struct. +// +// The following tags on struct fields have special meaning to Unmarshal: +// +// optional marks the field as ASN.1 OPTIONAL +// [explicit] tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC +// default:x sets the default value for optional integer fields +// +// If the type of the first field of a structure is RawContent then the raw +// ASN1 contents of the struct will be stored in it. +// +// Other ASN.1 types are not supported; if it encounters them, +// Unmarshal returns a parse error. +func Unmarshal(b []byte, val interface{}) (rest []byte, err error) { + return UnmarshalWithParams(b, val, "") +} + +// UnmarshalWithParams allows field parameters to be specified for the +// top-level element. The form of the params is the same as the field tags. +func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err error) { + v := reflect.ValueOf(val).Elem() + offset, err := parseField(v, b, 0, parseFieldParameters(params)) + if err != nil { + return nil, err + } + return b[offset:], nil +} diff --git a/libgo/go/encoding/asn1/asn1_test.go b/libgo/go/encoding/asn1/asn1_test.go new file mode 100644 index 0000000..1c529bd --- /dev/null +++ b/libgo/go/encoding/asn1/asn1_test.go @@ -0,0 +1,689 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package asn1 + +import ( + "bytes" + "reflect" + "testing" + "time" +) + +type int64Test struct { + in []byte + ok bool + out int64 +} + +var int64TestData = []int64Test{ + {[]byte{0x00}, true, 0}, + {[]byte{0x7f}, true, 127}, + {[]byte{0x00, 0x80}, true, 128}, + {[]byte{0x01, 0x00}, true, 256}, + {[]byte{0x80}, true, -128}, + {[]byte{0xff, 0x7f}, true, -129}, + {[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, true, -1}, + {[]byte{0xff}, true, -1}, + {[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, true, -9223372036854775808}, + {[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, false, 0}, +} + +func TestParseInt64(t *testing.T) { + for i, test := range int64TestData { + ret, err := parseInt64(test.in) + if (err == nil) != test.ok { + t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) + } + if test.ok && ret != test.out { + t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) + } + } +} + +type int32Test struct { + in []byte + ok bool + out int32 +} + +var int32TestData = []int32Test{ + {[]byte{0x00}, true, 0}, + {[]byte{0x7f}, true, 127}, + {[]byte{0x00, 0x80}, true, 128}, + {[]byte{0x01, 0x00}, true, 256}, + {[]byte{0x80}, true, -128}, + {[]byte{0xff, 0x7f}, true, -129}, + {[]byte{0xff, 0xff, 0xff, 0xff}, true, -1}, + {[]byte{0xff}, true, -1}, + {[]byte{0x80, 0x00, 0x00, 0x00}, true, -2147483648}, + {[]byte{0x80, 0x00, 0x00, 0x00, 0x00}, false, 0}, +} + +func TestParseInt32(t *testing.T) { + for i, test := range int32TestData { + ret, err := parseInt(test.in) + if (err == nil) != test.ok { + t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) + } + if test.ok && int32(ret) != test.out { + t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) + } + } +} + +var bigIntTests = []struct { + in []byte + base10 string +}{ + {[]byte{0xff}, "-1"}, + {[]byte{0x00}, "0"}, + {[]byte{0x01}, "1"}, + {[]byte{0x00, 0xff}, "255"}, + {[]byte{0xff, 0x00}, "-256"}, + {[]byte{0x01, 0x00}, "256"}, +} + +func TestParseBigInt(t *testing.T) { + for i, test := range bigIntTests { + ret := parseBigInt(test.in) + if ret.String() != test.base10 { + t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10) + } + fw := newForkableWriter() + marshalBigInt(fw, ret) + result := fw.Bytes() + if !bytes.Equal(result, test.in) { + t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in) + } + } +} + +type bitStringTest struct { + in []byte + ok bool + out []byte + bitLength int +} + +var bitStringTestData = []bitStringTest{ + {[]byte{}, false, []byte{}, 0}, + {[]byte{0x00}, true, []byte{}, 0}, + {[]byte{0x07, 0x00}, true, []byte{0x00}, 1}, + {[]byte{0x07, 0x01}, false, []byte{}, 0}, + {[]byte{0x07, 0x40}, false, []byte{}, 0}, + {[]byte{0x08, 0x00}, false, []byte{}, 0}, +} + +func TestBitString(t *testing.T) { + for i, test := range bitStringTestData { + ret, err := parseBitString(test.in) + if (err == nil) != test.ok { + t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) + } + if err == nil { + if test.bitLength != ret.BitLength || bytes.Compare(ret.Bytes, test.out) != 0 { + t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength) + } + } + } +} + +func TestBitStringAt(t *testing.T) { + bs := BitString{[]byte{0x82, 0x40}, 16} + if bs.At(0) != 1 { + t.Error("#1: Failed") + } + if bs.At(1) != 0 { + t.Error("#2: Failed") + } + if bs.At(6) != 1 { + t.Error("#3: Failed") + } + if bs.At(9) != 1 { + t.Error("#4: Failed") + } +} + +type bitStringRightAlignTest struct { + in []byte + inlen int + out []byte +} + +var bitStringRightAlignTests = []bitStringRightAlignTest{ + {[]byte{0x80}, 1, []byte{0x01}}, + {[]byte{0x80, 0x80}, 9, []byte{0x01, 0x01}}, + {[]byte{}, 0, []byte{}}, + {[]byte{0xce}, 8, []byte{0xce}}, + {[]byte{0xce, 0x47}, 16, []byte{0xce, 0x47}}, + {[]byte{0x34, 0x50}, 12, []byte{0x03, 0x45}}, +} + +func TestBitStringRightAlign(t *testing.T) { + for i, test := range bitStringRightAlignTests { + bs := BitString{test.in, test.inlen} + out := bs.RightAlign() + if bytes.Compare(out, test.out) != 0 { + t.Errorf("#%d got: %x want: %x", i, out, test.out) + } + } +} + +type objectIdentifierTest struct { + in []byte + ok bool + out []int +} + +var objectIdentifierTestData = []objectIdentifierTest{ + {[]byte{}, false, []int{}}, + {[]byte{85}, true, []int{2, 5}}, + {[]byte{85, 0x02}, true, []int{2, 5, 2}}, + {[]byte{85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}}, + {[]byte{85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}}, +} + +func TestObjectIdentifier(t *testing.T) { + for i, test := range objectIdentifierTestData { + ret, err := parseObjectIdentifier(test.in) + if (err == nil) != test.ok { + t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) + } + if err == nil { + if !reflect.DeepEqual(test.out, ret) { + t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) + } + } + } +} + +type timeTest struct { + in string + ok bool + out *time.Time +} + +var utcTestData = []timeTest{ + {"910506164540-0700", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, -7 * 60 * 60, ""}}, + {"910506164540+0730", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, 7*60*60 + 30*60, ""}}, + {"910506234540Z", true, &time.Time{1991, 05, 06, 23, 45, 40, 0, 0, "UTC"}}, + {"9105062345Z", true, &time.Time{1991, 05, 06, 23, 45, 0, 0, 0, "UTC"}}, + {"a10506234540Z", false, nil}, + {"91a506234540Z", false, nil}, + {"9105a6234540Z", false, nil}, + {"910506a34540Z", false, nil}, + {"910506334a40Z", false, nil}, + {"91050633444aZ", false, nil}, + {"910506334461Z", false, nil}, + {"910506334400Za", false, nil}, +} + +func TestUTCTime(t *testing.T) { + for i, test := range utcTestData { + ret, err := parseUTCTime([]byte(test.in)) + if (err == nil) != test.ok { + t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) + } + if err == nil { + if !reflect.DeepEqual(test.out, ret) { + t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) + } + } + } +} + +var generalizedTimeTestData = []timeTest{ + {"20100102030405Z", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, "UTC"}}, + {"20100102030405", false, nil}, + {"20100102030405+0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 6*60*60 + 7*60, ""}}, + {"20100102030405-0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, -6*60*60 - 7*60, ""}}, +} + +func TestGeneralizedTime(t *testing.T) { + for i, test := range generalizedTimeTestData { + ret, err := parseGeneralizedTime([]byte(test.in)) + if (err == nil) != test.ok { + t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) + } + if err == nil { + if !reflect.DeepEqual(test.out, ret) { + t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) + } + } + } +} + +type tagAndLengthTest struct { + in []byte + ok bool + out tagAndLength +} + +var tagAndLengthData = []tagAndLengthTest{ + {[]byte{0x80, 0x01}, true, tagAndLength{2, 0, 1, false}}, + {[]byte{0xa0, 0x01}, true, tagAndLength{2, 0, 1, true}}, + {[]byte{0x02, 0x00}, true, tagAndLength{0, 2, 0, false}}, + {[]byte{0xfe, 0x00}, true, tagAndLength{3, 30, 0, true}}, + {[]byte{0x1f, 0x01, 0x00}, true, tagAndLength{0, 1, 0, false}}, + {[]byte{0x1f, 0x81, 0x00, 0x00}, true, tagAndLength{0, 128, 0, false}}, + {[]byte{0x1f, 0x81, 0x80, 0x01, 0x00}, true, tagAndLength{0, 0x4001, 0, false}}, + {[]byte{0x00, 0x81, 0x01}, true, tagAndLength{0, 0, 1, false}}, + {[]byte{0x00, 0x82, 0x01, 0x00}, true, tagAndLength{0, 0, 256, false}}, + {[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}}, + {[]byte{0x1f, 0x85}, false, tagAndLength{}}, + {[]byte{0x30, 0x80}, false, tagAndLength{}}, +} + +func TestParseTagAndLength(t *testing.T) { + for i, test := range tagAndLengthData { + tagAndLength, _, err := parseTagAndLength(test.in, 0) + if (err == nil) != test.ok { + t.Errorf("#%d: Incorrect error result (did pass? %v, expected: %v)", i, err == nil, test.ok) + } + if err == nil && !reflect.DeepEqual(test.out, tagAndLength) { + t.Errorf("#%d: Bad result: %v (expected %v)", i, tagAndLength, test.out) + } + } +} + +type parseFieldParametersTest struct { + in string + out fieldParameters +} + +func newInt(n int) *int { return &n } + +func newInt64(n int64) *int64 { return &n } + +func newString(s string) *string { return &s } + +func newBool(b bool) *bool { return &b } + +var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{ + {"", fieldParameters{}}, + {"ia5", fieldParameters{stringType: tagIA5String}}, + {"printable", fieldParameters{stringType: tagPrintableString}}, + {"optional", fieldParameters{optional: true}}, + {"explicit", fieldParameters{explicit: true, tag: new(int)}}, + {"application", fieldParameters{application: true, tag: new(int)}}, + {"optional,explicit", fieldParameters{optional: true, explicit: true, tag: new(int)}}, + {"default:42", fieldParameters{defaultValue: newInt64(42)}}, + {"tag:17", fieldParameters{tag: newInt(17)}}, + {"optional,explicit,default:42,tag:17", fieldParameters{optional: true, explicit: true, defaultValue: newInt64(42), tag: newInt(17)}}, + {"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{true, true, false, newInt64(42), newInt(17), 0, false}}, + {"set", fieldParameters{set: true}}, +} + +func TestParseFieldParameters(t *testing.T) { + for i, test := range parseFieldParametersTestData { + f := parseFieldParameters(test.in) + if !reflect.DeepEqual(f, test.out) { + t.Errorf("#%d: Bad result: %v (expected %v)", i, f, test.out) + } + } +} + +type TestObjectIdentifierStruct struct { + OID ObjectIdentifier +} + +type TestContextSpecificTags struct { + A int `asn1:"tag:1"` +} + +type TestContextSpecificTags2 struct { + A int `asn1:"explicit,tag:1"` + B int +} + +type TestElementsAfterString struct { + S string + A, B int +} + +var unmarshalTestData = []struct { + in []byte + out interface{} +}{ + {[]byte{0x02, 0x01, 0x42}, newInt(0x42)}, + {[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}}, + {[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}}, + {[]byte{0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &[]int{1, 2, 3}}, + {[]byte{0x02, 0x01, 0x10}, newInt(16)}, + {[]byte{0x13, 0x04, 't', 'e', 's', 't'}, newString("test")}, + {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, newString("test")}, + {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, &RawValue{0, 22, false, []byte("test"), []byte("\x16\x04test")}}, + {[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}}, + {[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}}, + {[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}}, + {[]byte{0x01, 0x01, 0x00}, newBool(false)}, + {[]byte{0x01, 0x01, 0x01}, newBool(true)}, + {[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}}, +} + +func TestUnmarshal(t *testing.T) { + for i, test := range unmarshalTestData { + pv := reflect.New(reflect.TypeOf(test.out).Elem()) + val := pv.Interface() + _, err := Unmarshal(test.in, val) + if err != nil { + t.Errorf("Unmarshal failed at index %d %v", i, err) + } + if !reflect.DeepEqual(val, test.out) { + t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out) + } + } +} + +type Certificate struct { + TBSCertificate TBSCertificate + SignatureAlgorithm AlgorithmIdentifier + SignatureValue BitString +} + +type TBSCertificate struct { + Version int `asn1:"optional,explicit,default:0,tag:0"` + SerialNumber RawValue + SignatureAlgorithm AlgorithmIdentifier + Issuer RDNSequence + Validity Validity + Subject RDNSequence + PublicKey PublicKeyInfo +} + +type AlgorithmIdentifier struct { + Algorithm ObjectIdentifier +} + +type RDNSequence []RelativeDistinguishedNameSET + +type RelativeDistinguishedNameSET []AttributeTypeAndValue + +type AttributeTypeAndValue struct { + Type ObjectIdentifier + Value interface{} +} + +type Validity struct { + NotBefore, NotAfter *time.Time +} + +type PublicKeyInfo struct { + Algorithm AlgorithmIdentifier + PublicKey BitString +} + +func TestCertificate(t *testing.T) { + // This is a minimal, self-signed certificate that should parse correctly. + var cert Certificate + if _, err := Unmarshal(derEncodedSelfSignedCertBytes, &cert); err != nil { + t.Errorf("Unmarshal failed: %v", err) + } + if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) { + t.Errorf("Bad result:\ngot: %+v\nwant: %+v", cert, derEncodedSelfSignedCert) + } +} + +func TestCertificateWithNUL(t *testing.T) { + // This is the paypal NUL-hack certificate. It should fail to parse because + // NUL isn't a permitted character in a PrintableString. + + var cert Certificate + if _, err := Unmarshal(derEncodedPaypalNULCertBytes, &cert); err == nil { + t.Error("Unmarshal succeeded, should not have") + } +} + +type rawStructTest struct { + Raw RawContent + A int +} + +func TestRawStructs(t *testing.T) { + var s rawStructTest + input := []byte{0x30, 0x03, 0x02, 0x01, 0x50} + + rest, err := Unmarshal(input, &s) + if len(rest) != 0 { + t.Errorf("incomplete parse: %x", rest) + return + } + if err != nil { + t.Error(err) + return + } + if s.A != 0x50 { + t.Errorf("bad value for A: got %d want %d", s.A, 0x50) + } + if bytes.Compare([]byte(s.Raw), input) != 0 { + t.Errorf("bad value for Raw: got %x want %x", s.Raw, input) + } +} + +var derEncodedSelfSignedCert = Certificate{ + TBSCertificate: TBSCertificate{ + Version: 0, + SerialNumber: RawValue{Class: 0, Tag: 2, IsCompound: false, Bytes: []uint8{0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}, FullBytes: []byte{2, 9, 0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}}, + SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}}, + Issuer: RDNSequence{ + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, + }, + Validity: Validity{NotBefore: &time.Time{Year: 2009, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, ZoneOffset: 0, Zone: "UTC"}, NotAfter: &time.Time{Year: 2010, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, ZoneOffset: 0, Zone: "UTC"}}, + Subject: RDNSequence{ + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, + }, + PublicKey: PublicKeyInfo{ + Algorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}}, + PublicKey: BitString{ + Bytes: []uint8{ + 0x30, 0x48, 0x2, 0x41, 0x0, 0xcd, 0xb7, + 0x63, 0x9c, 0x32, 0x78, 0xf0, 0x6, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, + 0x90, 0x2b, 0x59, 0x2d, 0x8c, 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, + 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, + 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, 0x96, 0x57, 0x72, 0x2a, 0x4f, + 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, 0xdc, 0x8f, 0xde, 0xec, + 0x35, 0x7d, 0x2, 0x3, 0x1, 0x0, 0x1, + }, + BitLength: 592, + }, + }, + }, + SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}}, + SignatureValue: BitString{ + Bytes: []uint8{ + 0xa6, 0x7b, 0x6, 0xec, 0x5e, 0xce, + 0x92, 0x77, 0x2c, 0xa4, 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, + 0x7b, 0x45, 0x11, 0xcd, 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x4, 0x2, 0xdf, 0x2b, + 0x99, 0x8b, 0xb9, 0xa4, 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, + 0xd9, 0x1e, 0xde, 0x14, 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, + 0xfa, 0x88, 0x21, 0x49, 0x4, 0x35, + }, + BitLength: 512, + }, +} + +var derEncodedSelfSignedCertBytes = []byte{ + 0x30, 0x82, 0x02, 0x18, 0x30, + 0x82, 0x01, 0xc2, 0x02, 0x09, 0x00, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, + 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, + 0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, + 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, + 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, + 0x73, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, + 0x30, 0x39, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, 0x33, 0x5a, + 0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, + 0x33, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, 0x69, + 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, + 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x1a, + 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, 0x73, + 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xcd, 0xb7, 0x63, 0x9c, 0x32, 0x78, + 0xf0, 0x06, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, 0x90, 0x2b, 0x59, 0x2d, 0x8c, + 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, + 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, + 0x96, 0x57, 0x72, 0x2a, 0x4f, 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, + 0xdc, 0x8f, 0xde, 0xec, 0x35, 0x7d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x41, 0x00, 0xa6, 0x7b, 0x06, 0xec, 0x5e, 0xce, 0x92, 0x77, 0x2c, 0xa4, + 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, 0x7b, 0x45, 0x11, 0xcd, + 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x04, 0x02, 0xdf, 0x2b, 0x99, 0x8b, 0xb9, 0xa4, + 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, 0xd9, 0x1e, 0xde, 0x14, + 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, 0xfa, 0x88, 0x21, 0x49, + 0x04, 0x35, +} + +var derEncodedPaypalNULCertBytes = []byte{ + 0x30, 0x82, 0x06, 0x44, 0x30, + 0x82, 0x05, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x00, 0xf0, 0x9b, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x30, 0x82, 0x01, 0x12, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x09, 0x42, 0x61, 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x42, 0x61, + 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x50, 0x53, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x73, 0x2e, 0x6c, 0x2e, 0x31, 0x2e, + 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x25, 0x67, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, + 0x20, 0x43, 0x2e, 0x49, 0x2e, 0x46, 0x2e, 0x20, 0x20, 0x42, 0x2d, 0x42, 0x36, + 0x32, 0x32, 0x31, 0x30, 0x36, 0x39, 0x35, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x13, 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, + 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, + 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, + 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, + 0x01, 0x16, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, + 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39, + 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, 0x17, 0x0d, + 0x31, 0x31, 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, + 0x30, 0x81, 0x94, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, + 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, + 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x53, 0x61, 0x6e, 0x20, + 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x31, 0x11, 0x30, 0x0f, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x31, 0x2f, + 0x30, 0x2d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x26, 0x77, 0x77, 0x77, 0x2e, + 0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x73, 0x73, + 0x6c, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x63, 0x30, 0x81, 0x9f, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x69, + 0xfa, 0x6f, 0x3a, 0x00, 0xb4, 0x21, 0x1b, 0xc8, 0xb1, 0x02, 0xd7, 0x3f, 0x19, + 0xb2, 0xc4, 0x6d, 0xb4, 0x54, 0xf8, 0x8b, 0x8a, 0xcc, 0xdb, 0x72, 0xc2, 0x9e, + 0x3c, 0x60, 0xb9, 0xc6, 0x91, 0x3d, 0x82, 0xb7, 0x7d, 0x99, 0xff, 0xd1, 0x29, + 0x84, 0xc1, 0x73, 0x53, 0x9c, 0x82, 0xdd, 0xfc, 0x24, 0x8c, 0x77, 0xd5, 0x41, + 0xf3, 0xe8, 0x1e, 0x42, 0xa1, 0xad, 0x2d, 0x9e, 0xff, 0x5b, 0x10, 0x26, 0xce, + 0x9d, 0x57, 0x17, 0x73, 0x16, 0x23, 0x38, 0xc8, 0xd6, 0xf1, 0xba, 0xa3, 0x96, + 0x5b, 0x16, 0x67, 0x4a, 0x4f, 0x73, 0x97, 0x3a, 0x4d, 0x14, 0xa4, 0xf4, 0xe2, + 0x3f, 0x8b, 0x05, 0x83, 0x42, 0xd1, 0xd0, 0xdc, 0x2f, 0x7a, 0xe5, 0xb6, 0x10, + 0xb2, 0x11, 0xc0, 0xdc, 0x21, 0x2a, 0x90, 0xff, 0xae, 0x97, 0x71, 0x5a, 0x49, + 0x81, 0xac, 0x40, 0xf3, 0x3b, 0xb8, 0x59, 0xb2, 0x4f, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x82, 0x03, 0x21, 0x30, 0x82, 0x03, 0x1d, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40, + 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03, 0xf8, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x61, 0x8f, 0x61, 0x34, 0x43, 0x55, 0x14, + 0x7f, 0x27, 0x09, 0xce, 0x4c, 0x8b, 0xea, 0x9b, 0x7b, 0x19, 0x25, 0xbc, 0x6e, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x0e, 0x07, 0x60, 0xd4, 0x39, 0xc9, 0x1b, 0x5b, 0x5d, 0x90, 0x7b, 0x23, 0xc8, + 0xd2, 0x34, 0x9d, 0x4a, 0x9a, 0x46, 0x39, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, + 0x11, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x1d, 0x12, 0x04, + 0x15, 0x30, 0x13, 0x81, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, + 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x72, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x65, 0x16, 0x63, + 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e, + 0x4f, 0x54, 0x20, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x44, 0x2e, + 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68, + 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, + 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x2f, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x02, 0x04, 0x22, 0x16, 0x20, 0x68, + 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, + 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, + 0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x86, 0xf8, 0x42, 0x01, 0x04, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, + 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, + 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, + 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x46, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x03, 0x04, 0x39, 0x16, 0x37, + 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, + 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, + 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, + 0x6d, 0x6c, 0x3f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, + 0x42, 0x01, 0x07, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, + 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, + 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, + 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x30, 0x41, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x34, 0x16, 0x32, 0x68, 0x74, + 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, + 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, + 0x30, 0x30, 0x32, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x4c, 0x41, + 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x30, 0x81, 0x83, 0x06, + 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x7c, 0x30, 0x7a, 0x30, 0x39, 0xa0, 0x37, 0xa0, + 0x35, 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, + 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, + 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, + 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, + 0x72, 0x6c, 0x30, 0x3d, 0xa0, 0x3b, 0xa0, 0x39, 0x86, 0x37, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x69, + 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, + 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, + 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, + 0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, + 0x26, 0x30, 0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, + 0x73, 0x70, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x68, 0xee, 0x79, 0x97, 0x97, 0xdd, 0x3b, + 0xef, 0x16, 0x6a, 0x06, 0xf2, 0x14, 0x9a, 0x6e, 0xcd, 0x9e, 0x12, 0xf7, 0xaa, + 0x83, 0x10, 0xbd, 0xd1, 0x7c, 0x98, 0xfa, 0xc7, 0xae, 0xd4, 0x0e, 0x2c, 0x9e, + 0x38, 0x05, 0x9d, 0x52, 0x60, 0xa9, 0x99, 0x0a, 0x81, 0xb4, 0x98, 0x90, 0x1d, + 0xae, 0xbb, 0x4a, 0xd7, 0xb9, 0xdc, 0x88, 0x9e, 0x37, 0x78, 0x41, 0x5b, 0xf7, + 0x82, 0xa5, 0xf2, 0xba, 0x41, 0x25, 0x5a, 0x90, 0x1a, 0x1e, 0x45, 0x38, 0xa1, + 0x52, 0x58, 0x75, 0x94, 0x26, 0x44, 0xfb, 0x20, 0x07, 0xba, 0x44, 0xcc, 0xe5, + 0x4a, 0x2d, 0x72, 0x3f, 0x98, 0x47, 0xf6, 0x26, 0xdc, 0x05, 0x46, 0x05, 0x07, + 0x63, 0x21, 0xab, 0x46, 0x9b, 0x9c, 0x78, 0xd5, 0x54, 0x5b, 0x3d, 0x0c, 0x1e, + 0xc8, 0x64, 0x8c, 0xb5, 0x50, 0x23, 0x82, 0x6f, 0xdb, 0xb8, 0x22, 0x1c, 0x43, + 0x96, 0x07, 0xa8, 0xbb, +} diff --git a/libgo/go/encoding/asn1/common.go b/libgo/go/encoding/asn1/common.go new file mode 100644 index 0000000..01f4f7b --- /dev/null +++ b/libgo/go/encoding/asn1/common.go @@ -0,0 +1,158 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package asn1 + +import ( + "reflect" + "strconv" + "strings" +) + +// ASN.1 objects have metadata preceding them: +// the tag: the type of the object +// a flag denoting if this object is compound or not +// the class type: the namespace of the tag +// the length of the object, in bytes + +// Here are some standard tags and classes + +const ( + tagBoolean = 1 + tagInteger = 2 + tagBitString = 3 + tagOctetString = 4 + tagOID = 6 + tagEnum = 10 + tagUTF8String = 12 + tagSequence = 16 + tagSet = 17 + tagPrintableString = 19 + tagT61String = 20 + tagIA5String = 22 + tagUTCTime = 23 + tagGeneralizedTime = 24 + tagGeneralString = 27 +) + +const ( + classUniversal = 0 + classApplication = 1 + classContextSpecific = 2 + classPrivate = 3 +) + +type tagAndLength struct { + class, tag, length int + isCompound bool +} + +// ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead +// of" and "in addition to". When not specified, every primitive type has a +// default tag in the UNIVERSAL class. +// +// For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1 +// doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT +// CONTEXT-SPECIFIC 42], that means that the tag is replaced by another. +// +// On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an +// /additional/ tag would wrap the default tag. This explicit tag will have the +// compound flag set. +// +// (This is used in order to remove ambiguity with optional elements.) +// +// You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we +// don't support that here. We support a single layer of EXPLICIT or IMPLICIT +// tagging with tag strings on the fields of a structure. + +// fieldParameters is the parsed representation of tag string from a structure field. +type fieldParameters struct { + optional bool // true iff the field is OPTIONAL + explicit bool // true iff an EXPLICIT tag is in use. + application bool // true iff an APPLICATION tag is in use. + defaultValue *int64 // a default value for INTEGER typed fields (maybe nil). + tag *int // the EXPLICIT or IMPLICIT tag (maybe nil). + stringType int // the string tag to use when marshaling. + set bool // true iff this should be encoded as a SET + + // Invariants: + // if explicit is set, tag is non-nil. +} + +// Given a tag string with the format specified in the package comment, +// parseFieldParameters will parse it into a fieldParameters structure, +// ignoring unknown parts of the string. +func parseFieldParameters(str string) (ret fieldParameters) { + for _, part := range strings.Split(str, ",") { + switch { + case part == "optional": + ret.optional = true + case part == "explicit": + ret.explicit = true + if ret.tag == nil { + ret.tag = new(int) + } + case part == "ia5": + ret.stringType = tagIA5String + case part == "printable": + ret.stringType = tagPrintableString + case strings.HasPrefix(part, "default:"): + i, err := strconv.Atoi64(part[8:]) + if err == nil { + ret.defaultValue = new(int64) + *ret.defaultValue = i + } + case strings.HasPrefix(part, "tag:"): + i, err := strconv.Atoi(part[4:]) + if err == nil { + ret.tag = new(int) + *ret.tag = i + } + case part == "set": + ret.set = true + case part == "application": + ret.application = true + if ret.tag == nil { + ret.tag = new(int) + } + } + } + return +} + +// Given a reflected Go type, getUniversalType returns the default tag number +// and expected compound flag. +func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) { + switch t { + case objectIdentifierType: + return tagOID, false, true + case bitStringType: + return tagBitString, false, true + case timeType: + return tagUTCTime, false, true + case enumeratedType: + return tagEnum, false, true + case bigIntType: + return tagInteger, false, true + } + switch t.Kind() { + case reflect.Bool: + return tagBoolean, false, true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return tagInteger, false, true + case reflect.Struct: + return tagSequence, true, true + case reflect.Slice: + if t.Elem().Kind() == reflect.Uint8 { + return tagOctetString, false, true + } + if strings.HasSuffix(t.Name(), "SET") { + return tagSet, true, true + } + return tagSequence, true, true + case reflect.String: + return tagPrintableString, false, true + } + return 0, false, false +} diff --git a/libgo/go/encoding/asn1/marshal.go b/libgo/go/encoding/asn1/marshal.go new file mode 100644 index 0000000..89c50a7 --- /dev/null +++ b/libgo/go/encoding/asn1/marshal.go @@ -0,0 +1,547 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package asn1 + +import ( + "bytes" + "fmt" + "io" + "math/big" + "reflect" + "time" +) + +// A forkableWriter is an in-memory buffer that can be +// 'forked' to create new forkableWriters that bracket the +// original. After +// pre, post := w.fork(); +// the overall sequence of bytes represented is logically w+pre+post. +type forkableWriter struct { + *bytes.Buffer + pre, post *forkableWriter +} + +func newForkableWriter() *forkableWriter { + return &forkableWriter{bytes.NewBuffer(nil), nil, nil} +} + +func (f *forkableWriter) fork() (pre, post *forkableWriter) { + if f.pre != nil || f.post != nil { + panic("have already forked") + } + f.pre = newForkableWriter() + f.post = newForkableWriter() + return f.pre, f.post +} + +func (f *forkableWriter) Len() (l int) { + l += f.Buffer.Len() + if f.pre != nil { + l += f.pre.Len() + } + if f.post != nil { + l += f.post.Len() + } + return +} + +func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) { + n, err = out.Write(f.Bytes()) + if err != nil { + return + } + + var nn int + + if f.pre != nil { + nn, err = f.pre.writeTo(out) + n += nn + if err != nil { + return + } + } + + if f.post != nil { + nn, err = f.post.writeTo(out) + n += nn + } + return +} + +func marshalBase128Int(out *forkableWriter, n int64) (err error) { + if n == 0 { + err = out.WriteByte(0) + return + } + + l := 0 + for i := n; i > 0; i >>= 7 { + l++ + } + + for i := l - 1; i >= 0; i-- { + o := byte(n >> uint(i*7)) + o &= 0x7f + if i != 0 { + o |= 0x80 + } + err = out.WriteByte(o) + if err != nil { + return + } + } + + return nil +} + +func marshalInt64(out *forkableWriter, i int64) (err error) { + n := int64Length(i) + + for ; n > 0; n-- { + err = out.WriteByte(byte(i >> uint((n-1)*8))) + if err != nil { + return + } + } + + return nil +} + +func int64Length(i int64) (numBytes int) { + numBytes = 1 + + for i > 127 { + numBytes++ + i >>= 8 + } + + for i < -128 { + numBytes++ + i >>= 8 + } + + return +} + +func marshalBigInt(out *forkableWriter, n *big.Int) (err error) { + if n.Sign() < 0 { + // A negative number has to be converted to two's-complement + // form. So we'll subtract 1 and invert. If the + // most-significant-bit isn't set then we'll need to pad the + // beginning with 0xff in order to keep the number negative. + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bytes := nMinus1.Bytes() + for i := range bytes { + bytes[i] ^= 0xff + } + if len(bytes) == 0 || bytes[0]&0x80 == 0 { + err = out.WriteByte(0xff) + if err != nil { + return + } + } + _, err = out.Write(bytes) + } else if n.Sign() == 0 { + // Zero is written as a single 0 zero rather than no bytes. + err = out.WriteByte(0x00) + } else { + bytes := n.Bytes() + if len(bytes) > 0 && bytes[0]&0x80 != 0 { + // We'll have to pad this with 0x00 in order to stop it + // looking like a negative number. + err = out.WriteByte(0) + if err != nil { + return + } + } + _, err = out.Write(bytes) + } + return +} + +func marshalLength(out *forkableWriter, i int) (err error) { + n := lengthLength(i) + + for ; n > 0; n-- { + err = out.WriteByte(byte(i >> uint((n-1)*8))) + if err != nil { + return + } + } + + return nil +} + +func lengthLength(i int) (numBytes int) { + numBytes = 1 + for i > 255 { + numBytes++ + i >>= 8 + } + return +} + +func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) { + b := uint8(t.class) << 6 + if t.isCompound { + b |= 0x20 + } + if t.tag >= 31 { + b |= 0x1f + err = out.WriteByte(b) + if err != nil { + return + } + err = marshalBase128Int(out, int64(t.tag)) + if err != nil { + return + } + } else { + b |= uint8(t.tag) + err = out.WriteByte(b) + if err != nil { + return + } + } + + if t.length >= 128 { + l := lengthLength(t.length) + err = out.WriteByte(0x80 | byte(l)) + if err != nil { + return + } + err = marshalLength(out, t.length) + if err != nil { + return + } + } else { + err = out.WriteByte(byte(t.length)) + if err != nil { + return + } + } + + return nil +} + +func marshalBitString(out *forkableWriter, b BitString) (err error) { + paddingBits := byte((8 - b.BitLength%8) % 8) + err = out.WriteByte(paddingBits) + if err != nil { + return + } + _, err = out.Write(b.Bytes) + return +} + +func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) { + if len(oid) < 2 || oid[0] > 6 || oid[1] >= 40 { + return StructuralError{"invalid object identifier"} + } + + err = out.WriteByte(byte(oid[0]*40 + oid[1])) + if err != nil { + return + } + for i := 2; i < len(oid); i++ { + err = marshalBase128Int(out, int64(oid[i])) + if err != nil { + return + } + } + + return +} + +func marshalPrintableString(out *forkableWriter, s string) (err error) { + b := []byte(s) + for _, c := range b { + if !isPrintable(c) { + return StructuralError{"PrintableString contains invalid character"} + } + } + + _, err = out.Write(b) + return +} + +func marshalIA5String(out *forkableWriter, s string) (err error) { + b := []byte(s) + for _, c := range b { + if c > 127 { + return StructuralError{"IA5String contains invalid character"} + } + } + + _, err = out.Write(b) + return +} + +func marshalTwoDigits(out *forkableWriter, v int) (err error) { + err = out.WriteByte(byte('0' + (v/10)%10)) + if err != nil { + return + } + return out.WriteByte(byte('0' + v%10)) +} + +func marshalUTCTime(out *forkableWriter, t *time.Time) (err error) { + switch { + case 1950 <= t.Year && t.Year < 2000: + err = marshalTwoDigits(out, int(t.Year-1900)) + case 2000 <= t.Year && t.Year < 2050: + err = marshalTwoDigits(out, int(t.Year-2000)) + default: + return StructuralError{"Cannot represent time as UTCTime"} + } + + if err != nil { + return + } + + err = marshalTwoDigits(out, t.Month) + if err != nil { + return + } + + err = marshalTwoDigits(out, t.Day) + if err != nil { + return + } + + err = marshalTwoDigits(out, t.Hour) + if err != nil { + return + } + + err = marshalTwoDigits(out, t.Minute) + if err != nil { + return + } + + err = marshalTwoDigits(out, t.Second) + if err != nil { + return + } + + switch { + case t.ZoneOffset/60 == 0: + err = out.WriteByte('Z') + return + case t.ZoneOffset > 0: + err = out.WriteByte('+') + case t.ZoneOffset < 0: + err = out.WriteByte('-') + } + + if err != nil { + return + } + + offsetMinutes := t.ZoneOffset / 60 + if offsetMinutes < 0 { + offsetMinutes = -offsetMinutes + } + + err = marshalTwoDigits(out, offsetMinutes/60) + if err != nil { + return + } + + err = marshalTwoDigits(out, offsetMinutes%60) + return +} + +func stripTagAndLength(in []byte) []byte { + _, offset, err := parseTagAndLength(in, 0) + if err != nil { + return in + } + return in[offset:] +} + +func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) { + switch value.Type() { + case timeType: + return marshalUTCTime(out, value.Interface().(*time.Time)) + case bitStringType: + return marshalBitString(out, value.Interface().(BitString)) + case objectIdentifierType: + return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier)) + case bigIntType: + return marshalBigInt(out, value.Interface().(*big.Int)) + } + + switch v := value; v.Kind() { + case reflect.Bool: + if v.Bool() { + return out.WriteByte(255) + } else { + return out.WriteByte(0) + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return marshalInt64(out, int64(v.Int())) + case reflect.Struct: + t := v.Type() + + startingField := 0 + + // If the first element of the structure is a non-empty + // RawContents, then we don't bother serializing the rest. + if t.NumField() > 0 && t.Field(0).Type == rawContentsType { + s := v.Field(0) + if s.Len() > 0 { + bytes := make([]byte, s.Len()) + for i := 0; i < s.Len(); i++ { + bytes[i] = uint8(s.Index(i).Uint()) + } + /* The RawContents will contain the tag and + * length fields but we'll also be writing + * those ourselves, so we strip them out of + * bytes */ + _, err = out.Write(stripTagAndLength(bytes)) + return + } else { + startingField = 1 + } + } + + for i := startingField; i < t.NumField(); i++ { + var pre *forkableWriter + pre, out = out.fork() + err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1"))) + if err != nil { + return + } + } + return + case reflect.Slice: + sliceType := v.Type() + if sliceType.Elem().Kind() == reflect.Uint8 { + bytes := make([]byte, v.Len()) + for i := 0; i < v.Len(); i++ { + bytes[i] = uint8(v.Index(i).Uint()) + } + _, err = out.Write(bytes) + return + } + + var params fieldParameters + for i := 0; i < v.Len(); i++ { + var pre *forkableWriter + pre, out = out.fork() + err = marshalField(pre, v.Index(i), params) + if err != nil { + return + } + } + return + case reflect.String: + if params.stringType == tagIA5String { + return marshalIA5String(out, v.String()) + } else { + return marshalPrintableString(out, v.String()) + } + return + } + + return StructuralError{"unknown Go type"} +} + +func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) { + // If the field is an interface{} then recurse into it. + if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { + return marshalField(out, v.Elem(), params) + } + + if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { + return + } + + if v.Type() == rawValueType { + rv := v.Interface().(RawValue) + if len(rv.FullBytes) != 0 { + _, err = out.Write(rv.FullBytes) + } else { + err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}) + if err != nil { + return + } + _, err = out.Write(rv.Bytes) + } + return + } + + tag, isCompound, ok := getUniversalType(v.Type()) + if !ok { + err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} + return + } + class := classUniversal + + if params.stringType != 0 { + if tag != tagPrintableString { + return StructuralError{"Explicit string type given to non-string member"} + } + tag = params.stringType + } + + if params.set { + if tag != tagSequence { + return StructuralError{"Non sequence tagged as set"} + } + tag = tagSet + } + + tags, body := out.fork() + + err = marshalBody(body, v, params) + if err != nil { + return + } + + bodyLen := body.Len() + + var explicitTag *forkableWriter + if params.explicit { + explicitTag, tags = tags.fork() + } + + if !params.explicit && params.tag != nil { + // implicit tag. + tag = *params.tag + class = classContextSpecific + } + + err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound}) + if err != nil { + return + } + + if params.explicit { + err = marshalTagAndLength(explicitTag, tagAndLength{ + class: classContextSpecific, + tag: *params.tag, + length: bodyLen + tags.Len(), + isCompound: true, + }) + } + + return nil +} + +// Marshal returns the ASN.1 encoding of val. +func Marshal(val interface{}) ([]byte, error) { + var out bytes.Buffer + v := reflect.ValueOf(val) + f := newForkableWriter() + err := marshalField(f, v, fieldParameters{}) + if err != nil { + return nil, err + } + _, err = f.writeTo(&out) + return out.Bytes(), nil +} diff --git a/libgo/go/encoding/asn1/marshal_test.go b/libgo/go/encoding/asn1/marshal_test.go new file mode 100644 index 0000000..03df5f1 --- /dev/null +++ b/libgo/go/encoding/asn1/marshal_test.go @@ -0,0 +1,129 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package asn1 + +import ( + "bytes" + "encoding/hex" + "testing" + "time" +) + +type intStruct struct { + A int +} + +type twoIntStruct struct { + A int + B int +} + +type nestedStruct struct { + A intStruct +} + +type rawContentsStruct struct { + Raw RawContent + A int +} + +type implicitTagTest struct { + A int `asn1:"implicit,tag:5"` +} + +type explicitTagTest struct { + A int `asn1:"explicit,tag:5"` +} + +type ia5StringTest struct { + A string `asn1:"ia5"` +} + +type printableStringTest struct { + A string `asn1:"printable"` +} + +type optionalRawValueTest struct { + A RawValue `asn1:"optional"` +} + +type testSET []int + +func setPST(t *time.Time) *time.Time { + t.ZoneOffset = -28800 + return t +} + +type marshalTest struct { + in interface{} + out string // hex encoded +} + +var marshalTests = []marshalTest{ + {10, "02010a"}, + {127, "02017f"}, + {128, "02020080"}, + {-128, "020180"}, + {-129, "0202ff7f"}, + {intStruct{64}, "3003020140"}, + {twoIntStruct{64, 65}, "3006020140020141"}, + {nestedStruct{intStruct{127}}, "3005300302017f"}, + {[]byte{1, 2, 3}, "0403010203"}, + {implicitTagTest{64}, "3003850140"}, + {explicitTagTest{64}, "3005a503020140"}, + {time.SecondsToUTC(0), "170d3730303130313030303030305a"}, + {time.SecondsToUTC(1258325776), "170d3039313131353232353631365a"}, + {setPST(time.SecondsToUTC(1258325776)), "17113039313131353232353631362d30383030"}, + {BitString{[]byte{0x80}, 1}, "03020780"}, + {BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"}, + {ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"}, + {ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"}, + {"test", "130474657374"}, + { + "" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 127 times 'x' + "137f" + + "7878787878787878787878787878787878787878787878787878787878787878" + + "7878787878787878787878787878787878787878787878787878787878787878" + + "7878787878787878787878787878787878787878787878787878787878787878" + + "78787878787878787878787878787878787878787878787878787878787878", + }, + { + "" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 128 times 'x' + "138180" + + "7878787878787878787878787878787878787878787878787878787878787878" + + "7878787878787878787878787878787878787878787878787878787878787878" + + "7878787878787878787878787878787878787878787878787878787878787878" + + "7878787878787878787878787878787878787878787878787878787878787878", + }, + {ia5StringTest{"test"}, "3006160474657374"}, + {optionalRawValueTest{}, "3000"}, + {printableStringTest{"test"}, "3006130474657374"}, + {printableStringTest{"test*"}, "30071305746573742a"}, + {rawContentsStruct{nil, 64}, "3003020140"}, + {rawContentsStruct{[]byte{0x30, 3, 1, 2, 3}, 64}, "3003010203"}, + {RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"}, + {testSET([]int{10}), "310302010a"}, +} + +func TestMarshal(t *testing.T) { + for i, test := range marshalTests { + data, err := Marshal(test.in) + if err != nil { + t.Errorf("#%d failed: %s", i, err) + } + out, _ := hex.DecodeString(test.out) + if bytes.Compare(out, data) != 0 { + t.Errorf("#%d got: %x want %x", i, data, out) + } + } +} diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go index 65b9f01..d2f8b1e 100644 --- a/libgo/go/encoding/binary/binary.go +++ b/libgo/go/encoding/binary/binary.go @@ -9,8 +9,8 @@ package binary import ( "errors" - "math" "io" + "math" "reflect" ) diff --git a/libgo/go/encoding/binary/binary_test.go b/libgo/go/encoding/binary/binary_test.go index e753aa0..fd4fdb0 100644 --- a/libgo/go/encoding/binary/binary_test.go +++ b/libgo/go/encoding/binary/binary_test.go @@ -7,7 +7,6 @@ package binary import ( "bytes" "io" - "bytes" "math" "reflect" "testing" diff --git a/libgo/go/encoding/csv/reader.go b/libgo/go/encoding/csv/reader.go new file mode 100644 index 0000000..ae0f567 --- /dev/null +++ b/libgo/go/encoding/csv/reader.go @@ -0,0 +1,372 @@ +// 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 csv reads and writes comma-separated values (CSV) files. +// +// A csv file contains zero or more records of one or more fields per record. +// Each record is separated by the newline character. The final record may +// optionally be followed by a newline character. +// +// field1,field2,field3 +// +// White space is considered part of a field. +// +// Carriage returns before newline characters are silently removed. +// +// Blank lines are ignored. A line with only whitespace characters (excluding +// the ending newline character) is not considered a blank line. +// +// Fields which start and stop with the quote character " are called +// quoted-fields. The beginning and ending quote are not part of the +// field. +// +// The source: +// +// normal string,"quoted-field" +// +// results in the fields +// +// {`normal string`, `quoted-field`} +// +// Within a quoted-field a quote character followed by a second quote +// character is considered a single quote. +// +// "the ""word"" is true","a ""quoted-field""" +// +// results in +// +// {`the "word" is true`, `a "quoted-field"`} +// +// Newlines and commas may be included in a quoted-field +// +// "Multi-line +// field","comma is ," +// +// results in +// +// {`Multi-line +// field`, `comma is ,`} +package csv + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "unicode" +) + +// A ParseError is returned for parsing errors. +// The first line is 1. The first column is 0. +type ParseError struct { + Line int // Line where the error occurred + Column int // Column (rune index) where the error occurred + Err error // The actual error +} + +func (e *ParseError) Error() string { + return fmt.Sprintf("line %d, column %d: %s", e.Line, e.Column, e.Err) +} + +// These are the errors that can be returned in ParseError.Error +var ( + ErrTrailingComma = errors.New("extra delimiter at end of line") + ErrBareQuote = errors.New("bare \" in non-quoted-field") + ErrQuote = errors.New("extraneous \" in field") + ErrFieldCount = errors.New("wrong number of fields in line") +) + +// A Reader reads records from a CSV-encoded file. +// +// As returned by NewReader, a Reader expects input conforming to RFC 4180. +// The exported fields can be changed to customize the details before the +// first call to Read or ReadAll. +// +// Comma is the field delimiter. It defaults to ','. +// +// Comment, if not 0, is the comment character. Lines beginning with the +// Comment character are ignored. +// +// If FieldsPerRecord is positive, Read requires each record to +// have the given number of fields. If FieldsPerRecord is 0, Read sets it to +// the number of fields in the first record, so that future records must +// have the same field count. +// +// If LazyQuotes is true, a quote may appear in an unquoted field and a +// non-doubled quote may appear in a quoted field. +// +// If TrailingComma is true, the last field may be an unquoted empty field. +// +// If TrimLeadingSpace is true, leading white space in a field is ignored. +type Reader struct { + Comma rune // Field delimiter (set to ',' by NewReader) + Comment rune // Comment character for start of line + FieldsPerRecord int // Number of expected fields per record + LazyQuotes bool // Allow lazy quotes + TrailingComma bool // Allow trailing comma + TrimLeadingSpace bool // Trim leading space + line int + column int + r *bufio.Reader + field bytes.Buffer +} + +// NewReader returns a new Reader that reads from r. +func NewReader(r io.Reader) *Reader { + return &Reader{ + Comma: ',', + r: bufio.NewReader(r), + } +} + +// error creates a new ParseError based on err. +func (r *Reader) error(err error) error { + return &ParseError{ + Line: r.line, + Column: r.column, + Err: err, + } +} + +// Read reads one record from r. The record is a slice of strings with each +// string representing one field. +func (r *Reader) Read() (record []string, err error) { + for { + record, err = r.parseRecord() + if record != nil { + break + } + if err != nil { + return nil, err + } + } + + if r.FieldsPerRecord > 0 { + if len(record) != r.FieldsPerRecord { + r.column = 0 // report at start of record + return record, r.error(ErrFieldCount) + } + } else if r.FieldsPerRecord == 0 { + r.FieldsPerRecord = len(record) + } + return record, nil +} + +// ReadAll reads all the remaining records from r. +// Each record is a slice of fields. +func (r *Reader) ReadAll() (records [][]string, err error) { + for { + record, err := r.Read() + if err == io.EOF { + return records, nil + } + if err != nil { + return nil, err + } + records = append(records, record) + } + panic("unreachable") +} + +// readRune reads one rune from r, folding \r\n to \n and keeping track +// of how far into the line we have read. r.column will point to the start +// of this rune, not the end of this rune. +func (r *Reader) readRune() (rune, error) { + r1, _, err := r.r.ReadRune() + + // Handle \r\n here. We make the simplifying assumption that + // anytime \r is followed by \n that it can be folded to \n. + // We will not detect files which contain both \r\n and bare \n. + if r1 == '\r' { + r1, _, err = r.r.ReadRune() + if err == nil { + if r1 != '\n' { + r.r.UnreadRune() + r1 = '\r' + } + } + } + r.column++ + return r1, err +} + +// unreadRune puts the last rune read from r back. +func (r *Reader) unreadRune() { + r.r.UnreadRune() + r.column-- +} + +// skip reads runes up to and including the rune delim or until error. +func (r *Reader) skip(delim rune) error { + for { + r1, err := r.readRune() + if err != nil { + return err + } + if r1 == delim { + return nil + } + } + panic("unreachable") +} + +// parseRecord reads and parses a single csv record from r. +func (r *Reader) parseRecord() (fields []string, err error) { + // Each record starts on a new line. We increment our line + // number (lines start at 1, not 0) and set column to -1 + // so as we increment in readRune it points to the character we read. + r.line++ + r.column = -1 + + // Peek at the first rune. If it is an error we are done. + // If we are support comments and it is the comment character + // then skip to the end of line. + + r1, _, err := r.r.ReadRune() + if err != nil { + return nil, err + } + + if r.Comment != 0 && r1 == r.Comment { + return nil, r.skip('\n') + } + r.r.UnreadRune() + + // At this point we have at least one field. + for { + haveField, delim, err := r.parseField() + if haveField { + fields = append(fields, r.field.String()) + } + if delim == '\n' || err == io.EOF { + return fields, err + } else if err != nil { + return nil, err + } + } + panic("unreachable") +} + +// parseField parses the next field in the record. The read field is +// located in r.field. Delim is the first character not part of the field +// (r.Comma or '\n'). +func (r *Reader) parseField() (haveField bool, delim rune, err error) { + r.field.Reset() + + r1, err := r.readRune() + if err != nil { + // If we have EOF and are not at the start of a line + // then we return the empty field. We have already + // checked for trailing commas if needed. + if err == io.EOF && r.column != 0 { + return true, 0, err + } + return false, 0, err + } + + if r.TrimLeadingSpace { + for r1 != '\n' && unicode.IsSpace(r1) { + r1, err = r.readRune() + if err != nil { + return false, 0, err + } + } + } + + switch r1 { + case r.Comma: + // will check below + + case '\n': + // We are a trailing empty field or a blank line + if r.column == 0 { + return false, r1, nil + } + return true, r1, nil + + case '"': + // quoted field + Quoted: + for { + r1, err = r.readRune() + if err != nil { + if err == io.EOF { + if r.LazyQuotes { + return true, 0, err + } + return false, 0, r.error(ErrQuote) + } + return false, 0, err + } + switch r1 { + case '"': + r1, err = r.readRune() + if err != nil || r1 == r.Comma { + break Quoted + } + if r1 == '\n' { + return true, r1, nil + } + if r1 != '"' { + if !r.LazyQuotes { + r.column-- + return false, 0, r.error(ErrQuote) + } + // accept the bare quote + r.field.WriteRune('"') + } + case '\n': + r.line++ + r.column = -1 + } + r.field.WriteRune(r1) + } + + default: + // unquoted field + for { + r.field.WriteRune(r1) + r1, err = r.readRune() + if err != nil || r1 == r.Comma { + break + } + if r1 == '\n' { + return true, r1, nil + } + if !r.LazyQuotes && r1 == '"' { + return false, 0, r.error(ErrBareQuote) + } + } + } + + if err != nil { + if err == io.EOF { + return true, 0, err + } + return false, 0, err + } + + if !r.TrailingComma { + // We don't allow trailing commas. See if we + // are at the end of the line (being mindful + // of trimming spaces). + c := r.column + r1, err = r.readRune() + if r.TrimLeadingSpace { + for r1 != '\n' && unicode.IsSpace(r1) { + r1, err = r.readRune() + if err != nil { + break + } + } + } + if err == io.EOF || r1 == '\n' { + r.column = c // report the comma + return false, 0, r.error(ErrTrailingComma) + } + r.unreadRune() + } + return true, r1, nil +} diff --git a/libgo/go/encoding/csv/reader_test.go b/libgo/go/encoding/csv/reader_test.go new file mode 100644 index 0000000..5fd84a7 --- /dev/null +++ b/libgo/go/encoding/csv/reader_test.go @@ -0,0 +1,281 @@ +// 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 csv + +import ( + "reflect" + "strings" + "testing" +) + +var readTests = []struct { + Name string + Input string + Output [][]string + UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1 + + // These fields are copied into the Reader + Comma rune + Comment rune + FieldsPerRecord int + LazyQuotes bool + TrailingComma bool + TrimLeadingSpace bool + + Error string + Line int // Expected error line if != 0 + Column int // Expected error column if line != 0 +}{ + { + Name: "Simple", + Input: "a,b,c\n", + Output: [][]string{{"a", "b", "c"}}, + }, + { + Name: "CRLF", + Input: "a,b\r\nc,d\r\n", + Output: [][]string{{"a", "b"}, {"c", "d"}}, + }, + { + Name: "BareCR", + Input: "a,b\rc,d\r\n", + Output: [][]string{{"a", "b\rc", "d"}}, + }, + { + Name: "RFC4180test", + UseFieldsPerRecord: true, + Input: `#field1,field2,field3 +"aaa","bb +b","ccc" +"a,a","b""bb","ccc" +zzz,yyy,xxx +`, + Output: [][]string{ + {"#field1", "field2", "field3"}, + {"aaa", "bb\nb", "ccc"}, + {"a,a", `b"bb`, "ccc"}, + {"zzz", "yyy", "xxx"}, + }, + }, + { + Name: "NoEOLTest", + Input: "a,b,c", + Output: [][]string{{"a", "b", "c"}}, + }, + { + Name: "Semicolon", + Comma: ';', + Input: "a;b;c\n", + Output: [][]string{{"a", "b", "c"}}, + }, + { + Name: "MultiLine", + Input: `"two +line","one line","three +line +field"`, + Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}}, + }, + { + Name: "BlankLine", + Input: "a,b,c\n\nd,e,f\n\n", + Output: [][]string{ + {"a", "b", "c"}, + {"d", "e", "f"}, + }, + }, + { + Name: "TrimSpace", + Input: " a, b, c\n", + TrimLeadingSpace: true, + Output: [][]string{{"a", "b", "c"}}, + }, + { + Name: "LeadingSpace", + Input: " a, b, c\n", + Output: [][]string{{" a", " b", " c"}}, + }, + { + Name: "Comment", + Comment: '#', + Input: "#1,2,3\na,b,c\n#comment", + Output: [][]string{{"a", "b", "c"}}, + }, + { + Name: "NoComment", + Input: "#1,2,3\na,b,c", + Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}}, + }, + { + Name: "LazyQuotes", + LazyQuotes: true, + Input: `a "word","1"2",a","b`, + Output: [][]string{{`a "word"`, `1"2`, `a"`, `b`}}, + }, + { + Name: "BareQuotes", + LazyQuotes: true, + Input: `a "word","1"2",a"`, + Output: [][]string{{`a "word"`, `1"2`, `a"`}}, + }, + { + Name: "BareDoubleQuotes", + LazyQuotes: true, + Input: `a""b,c`, + Output: [][]string{{`a""b`, `c`}}, + }, + { + Name: "BadDoubleQuotes", + Input: `a""b,c`, + Error: `bare " in non-quoted-field`, Line: 1, Column: 1, + }, + { + Name: "TrimQuote", + Input: ` "a"," b",c`, + TrimLeadingSpace: true, + Output: [][]string{{"a", " b", "c"}}, + }, + { + Name: "BadBareQuote", + Input: `a "word","b"`, + Error: `bare " in non-quoted-field`, Line: 1, Column: 2, + }, + { + Name: "BadTrailingQuote", + Input: `"a word",b"`, + Error: `bare " in non-quoted-field`, Line: 1, Column: 10, + }, + { + Name: "ExtraneousQuote", + Input: `"a "word","b"`, + Error: `extraneous " in field`, Line: 1, Column: 3, + }, + { + Name: "BadFieldCount", + UseFieldsPerRecord: true, + Input: "a,b,c\nd,e", + Error: "wrong number of fields", Line: 2, + }, + { + Name: "BadFieldCount1", + UseFieldsPerRecord: true, + FieldsPerRecord: 2, + Input: `a,b,c`, + Error: "wrong number of fields", Line: 1, + }, + { + Name: "FieldCount", + Input: "a,b,c\nd,e", + Output: [][]string{{"a", "b", "c"}, {"d", "e"}}, + }, + { + Name: "BadTrailingCommaEOF", + Input: "a,b,c,", + Error: "extra delimiter at end of line", Line: 1, Column: 5, + }, + { + Name: "BadTrailingCommaEOL", + Input: "a,b,c,\n", + Error: "extra delimiter at end of line", Line: 1, Column: 5, + }, + { + Name: "BadTrailingCommaSpaceEOF", + TrimLeadingSpace: true, + Input: "a,b,c, ", + Error: "extra delimiter at end of line", Line: 1, Column: 5, + }, + { + Name: "BadTrailingCommaSpaceEOL", + TrimLeadingSpace: true, + Input: "a,b,c, \n", + Error: "extra delimiter at end of line", Line: 1, Column: 5, + }, + { + Name: "BadTrailingCommaLine3", + TrimLeadingSpace: true, + Input: "a,b,c\nd,e,f\ng,hi,", + Error: "extra delimiter at end of line", Line: 3, Column: 4, + }, + { + Name: "NotTrailingComma3", + Input: "a,b,c, \n", + Output: [][]string{{"a", "b", "c", " "}}, + }, + { + Name: "CommaFieldTest", + TrailingComma: true, + Input: `x,y,z,w +x,y,z, +x,y,, +x,,, +,,, +"x","y","z","w" +"x","y","z","" +"x","y","","" +"x","","","" +"","","","" +`, + Output: [][]string{ + {"x", "y", "z", "w"}, + {"x", "y", "z", ""}, + {"x", "y", "", ""}, + {"x", "", "", ""}, + {"", "", "", ""}, + {"x", "y", "z", "w"}, + {"x", "y", "z", ""}, + {"x", "y", "", ""}, + {"x", "", "", ""}, + {"", "", "", ""}, + }, + }, + { + Name: "Issue 2366", + TrailingComma: true, + TrimLeadingSpace: true, + Input: "a,b,\nc,d,e", + Output: [][]string{ + {"a", "b", ""}, + {"c", "d", "e"}, + }, + }, + { + Name: "Issue 2366a", + TrailingComma: false, + TrimLeadingSpace: true, + Input: "a,b,\nc,d,e", + Error: "extra delimiter at end of line", + }, +} + +func TestRead(t *testing.T) { + for _, tt := range readTests { + r := NewReader(strings.NewReader(tt.Input)) + r.Comment = tt.Comment + if tt.UseFieldsPerRecord { + r.FieldsPerRecord = tt.FieldsPerRecord + } else { + r.FieldsPerRecord = -1 + } + r.LazyQuotes = tt.LazyQuotes + r.TrailingComma = tt.TrailingComma + r.TrimLeadingSpace = tt.TrimLeadingSpace + if tt.Comma != 0 { + r.Comma = tt.Comma + } + out, err := r.ReadAll() + perr, _ := err.(*ParseError) + if tt.Error != "" { + if err == nil || !strings.Contains(err.Error(), tt.Error) { + t.Errorf("%s: error %v, want error %q", tt.Name, err, tt.Error) + } else if tt.Line != 0 && (tt.Line != perr.Line || tt.Column != perr.Column) { + t.Errorf("%s: error at %d:%d expected %d:%d", tt.Name, perr.Line, perr.Column, tt.Line, tt.Column) + } + } else if err != nil { + t.Errorf("%s: unexpected error %v", tt.Name, err) + } else if !reflect.DeepEqual(out, tt.Output) { + t.Errorf("%s: out=%q want %q", tt.Name, out, tt.Output) + } + } +} diff --git a/libgo/go/encoding/csv/writer.go b/libgo/go/encoding/csv/writer.go new file mode 100644 index 0000000..c4dcba5 --- /dev/null +++ b/libgo/go/encoding/csv/writer.go @@ -0,0 +1,121 @@ +// 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 csv + +import ( + "bufio" + "io" + "strings" + "unicode" + "unicode/utf8" +) + +// A Writer writes records to a CSV encoded file. +// +// As returned by NewWriter, a Writer writes records terminated by a +// newline and uses ',' as the field delimiter. The exported fields can be +// changed to customize the details before the first call to Write or WriteAll. +// +// Comma is the field delimiter. +// +// If UseCRLF is true, the Writer ends each record with \r\n instead of \n. +type Writer struct { + Comma rune // Field delimiter (set to to ',' by NewWriter) + UseCRLF bool // True to use \r\n as the line terminator + w *bufio.Writer +} + +// NewWriter returns a new Writer that writes to w. +func NewWriter(w io.Writer) *Writer { + return &Writer{ + Comma: ',', + w: bufio.NewWriter(w), + } +} + +// Writer writes a single CSV record to w along with any necessary quoting. +// A record is a slice of strings with each string being one field. +func (w *Writer) Write(record []string) (err error) { + for n, field := range record { + if n > 0 { + if _, err = w.w.WriteRune(w.Comma); err != nil { + return + } + } + + // If we don't have to have a quoted field then just + // write out the field and continue to the next field. + if !w.fieldNeedsQuotes(field) { + if _, err = w.w.WriteString(field); err != nil { + return + } + continue + } + if err = w.w.WriteByte('"'); err != nil { + return + } + + for _, r1 := range field { + switch r1 { + case '"': + _, err = w.w.WriteString(`""`) + case '\r': + if !w.UseCRLF { + err = w.w.WriteByte('\r') + } + case '\n': + if w.UseCRLF { + _, err = w.w.WriteString("\r\n") + } else { + err = w.w.WriteByte('\n') + } + default: + _, err = w.w.WriteRune(r1) + } + if err != nil { + return + } + } + + if err = w.w.WriteByte('"'); err != nil { + return + } + } + if w.UseCRLF { + _, err = w.w.WriteString("\r\n") + } else { + err = w.w.WriteByte('\n') + } + return +} + +// Flush writes any buffered data to the underlying io.Writer. +func (w *Writer) Flush() { + w.w.Flush() +} + +// WriteAll writes multiple CSV records to w using Write and then calls Flush. +func (w *Writer) WriteAll(records [][]string) (err error) { + for _, record := range records { + err = w.Write(record) + if err != nil { + break + } + } + w.Flush() + return nil +} + +// fieldNeedsQuotes returns true if our field must be enclosed in quotes. +// Empty fields, files with a Comma, fields with a quote or newline, and +// fields which start with a space must be enclosed in quotes. +func (w *Writer) fieldNeedsQuotes(field string) bool { + if len(field) == 0 || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 { + return true + } + + r1, _ := utf8.DecodeRuneInString(field) + return unicode.IsSpace(r1) +} diff --git a/libgo/go/encoding/csv/writer_test.go b/libgo/go/encoding/csv/writer_test.go new file mode 100644 index 0000000..5789590 --- /dev/null +++ b/libgo/go/encoding/csv/writer_test.go @@ -0,0 +1,44 @@ +// 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 csv + +import ( + "bytes" + "testing" +) + +var writeTests = []struct { + Input [][]string + Output string + UseCRLF bool +}{ + {Input: [][]string{{"abc"}}, Output: "abc\n"}, + {Input: [][]string{{"abc"}}, Output: "abc\r\n", UseCRLF: true}, + {Input: [][]string{{`"abc"`}}, Output: `"""abc"""` + "\n"}, + {Input: [][]string{{`a"b`}}, Output: `"a""b"` + "\n"}, + {Input: [][]string{{`"a"b"`}}, Output: `"""a""b"""` + "\n"}, + {Input: [][]string{{" abc"}}, Output: `" abc"` + "\n"}, + {Input: [][]string{{"abc,def"}}, Output: `"abc,def"` + "\n"}, + {Input: [][]string{{"abc", "def"}}, Output: "abc,def\n"}, + {Input: [][]string{{"abc"}, {"def"}}, Output: "abc\ndef\n"}, + {Input: [][]string{{"abc\ndef"}}, Output: "\"abc\ndef\"\n"}, + {Input: [][]string{{"abc\ndef"}}, Output: "\"abc\r\ndef\"\r\n", UseCRLF: true}, +} + +func TestWrite(t *testing.T) { + for n, tt := range writeTests { + b := &bytes.Buffer{} + f := NewWriter(b) + f.UseCRLF = tt.UseCRLF + err := f.WriteAll(tt.Input) + if err != nil { + t.Errorf("Unexpected error: %s\n", err) + } + out := b.String() + if out != tt.Output { + t.Errorf("#%d: out=%q want %q", n, out, tt.Output) + } + } +} diff --git a/libgo/go/encoding/gob/codec_test.go b/libgo/go/encoding/gob/codec_test.go new file mode 100644 index 0000000..dc0e007 --- /dev/null +++ b/libgo/go/encoding/gob/codec_test.go @@ -0,0 +1,1406 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import ( + "bytes" + "errors" + "math" + "reflect" + "strings" + "testing" + "unsafe" +) + +// Guarantee encoding format by comparing some encodings to hand-written values +type EncodeT struct { + x uint64 + b []byte +} + +var encodeT = []EncodeT{ + {0x00, []byte{0x00}}, + {0x0F, []byte{0x0F}}, + {0xFF, []byte{0xFF, 0xFF}}, + {0xFFFF, []byte{0xFE, 0xFF, 0xFF}}, + {0xFFFFFF, []byte{0xFD, 0xFF, 0xFF, 0xFF}}, + {0xFFFFFFFF, []byte{0xFC, 0xFF, 0xFF, 0xFF, 0xFF}}, + {0xFFFFFFFFFF, []byte{0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, + {0xFFFFFFFFFFFF, []byte{0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, + {0xFFFFFFFFFFFFFF, []byte{0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, + {0xFFFFFFFFFFFFFFFF, []byte{0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, + {0x1111, []byte{0xFE, 0x11, 0x11}}, + {0x1111111111111111, []byte{0xF8, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}}, + {0x8888888888888888, []byte{0xF8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}}, + {1 << 63, []byte{0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +} + +// testError is meant to be used as a deferred function to turn a panic(gobError) into a +// plain test.Error call. +func testError(t *testing.T) { + if e := recover(); e != nil { + t.Error(e.(gobError).err) // Will re-panic if not one of our errors, such as a runtime error. + } + return +} + +// Test basic encode/decode routines for unsigned integers +func TestUintCodec(t *testing.T) { + defer testError(t) + b := new(bytes.Buffer) + encState := newEncoderState(b) + for _, tt := range encodeT { + b.Reset() + encState.encodeUint(tt.x) + if !bytes.Equal(tt.b, b.Bytes()) { + t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes()) + } + } + decState := newDecodeState(b) + for u := uint64(0); ; u = (u + 1) * 7 { + b.Reset() + encState.encodeUint(u) + v := decState.decodeUint() + if u != v { + t.Errorf("Encode/Decode: sent %#x received %#x", u, v) + } + if u&(1<<63) != 0 { + break + } + } +} + +func verifyInt(i int64, t *testing.T) { + defer testError(t) + var b = new(bytes.Buffer) + encState := newEncoderState(b) + encState.encodeInt(i) + decState := newDecodeState(b) + decState.buf = make([]byte, 8) + j := decState.decodeInt() + if i != j { + t.Errorf("Encode/Decode: sent %#x received %#x", uint64(i), uint64(j)) + } +} + +// Test basic encode/decode routines for signed integers +func TestIntCodec(t *testing.T) { + for u := uint64(0); ; u = (u + 1) * 7 { + // Do positive and negative values + i := int64(u) + verifyInt(i, t) + verifyInt(-i, t) + verifyInt(^i, t) + if u&(1<<63) != 0 { + break + } + } + verifyInt(-1<<63, t) // a tricky case +} + +// The result of encoding a true boolean with field number 7 +var boolResult = []byte{0x07, 0x01} +// The result of encoding a number 17 with field number 7 +var signedResult = []byte{0x07, 2 * 17} +var unsignedResult = []byte{0x07, 17} +var floatResult = []byte{0x07, 0xFE, 0x31, 0x40} +// The result of encoding a number 17+19i with field number 7 +var complexResult = []byte{0x07, 0xFE, 0x31, 0x40, 0xFE, 0x33, 0x40} +// The result of encoding "hello" with field number 7 +var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'} + +func newDecodeState(buf *bytes.Buffer) *decoderState { + d := new(decoderState) + d.b = buf + d.buf = make([]byte, uint64Size) + return d +} + +func newEncoderState(b *bytes.Buffer) *encoderState { + b.Reset() + state := &encoderState{enc: nil, b: b} + state.fieldnum = -1 + return state +} + +// Test instruction execution for encoding. +// Do not run the machine yet; instead do individual instructions crafted by hand. +func TestScalarEncInstructions(t *testing.T) { + var b = new(bytes.Buffer) + + // bool + { + data := struct{ a bool }{true} + instr := &encInstr{encBool, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(boolResult, b.Bytes()) { + t.Errorf("bool enc instructions: expected % x got % x", boolResult, b.Bytes()) + } + } + + // int + { + b.Reset() + data := struct{ a int }{17} + instr := &encInstr{encInt, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(signedResult, b.Bytes()) { + t.Errorf("int enc instructions: expected % x got % x", signedResult, b.Bytes()) + } + } + + // uint + { + b.Reset() + data := struct{ a uint }{17} + instr := &encInstr{encUint, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(unsignedResult, b.Bytes()) { + t.Errorf("uint enc instructions: expected % x got % x", unsignedResult, b.Bytes()) + } + } + + // int8 + { + b.Reset() + data := struct{ a int8 }{17} + instr := &encInstr{encInt8, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(signedResult, b.Bytes()) { + t.Errorf("int8 enc instructions: expected % x got % x", signedResult, b.Bytes()) + } + } + + // uint8 + { + b.Reset() + data := struct{ a uint8 }{17} + instr := &encInstr{encUint8, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(unsignedResult, b.Bytes()) { + t.Errorf("uint8 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) + } + } + + // int16 + { + b.Reset() + data := struct{ a int16 }{17} + instr := &encInstr{encInt16, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(signedResult, b.Bytes()) { + t.Errorf("int16 enc instructions: expected % x got % x", signedResult, b.Bytes()) + } + } + + // uint16 + { + b.Reset() + data := struct{ a uint16 }{17} + instr := &encInstr{encUint16, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(unsignedResult, b.Bytes()) { + t.Errorf("uint16 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) + } + } + + // int32 + { + b.Reset() + data := struct{ a int32 }{17} + instr := &encInstr{encInt32, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(signedResult, b.Bytes()) { + t.Errorf("int32 enc instructions: expected % x got % x", signedResult, b.Bytes()) + } + } + + // uint32 + { + b.Reset() + data := struct{ a uint32 }{17} + instr := &encInstr{encUint32, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(unsignedResult, b.Bytes()) { + t.Errorf("uint32 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) + } + } + + // int64 + { + b.Reset() + data := struct{ a int64 }{17} + instr := &encInstr{encInt64, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(signedResult, b.Bytes()) { + t.Errorf("int64 enc instructions: expected % x got % x", signedResult, b.Bytes()) + } + } + + // uint64 + { + b.Reset() + data := struct{ a uint64 }{17} + instr := &encInstr{encUint64, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(unsignedResult, b.Bytes()) { + t.Errorf("uint64 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) + } + } + + // float32 + { + b.Reset() + data := struct{ a float32 }{17} + instr := &encInstr{encFloat32, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(floatResult, b.Bytes()) { + t.Errorf("float32 enc instructions: expected % x got % x", floatResult, b.Bytes()) + } + } + + // float64 + { + b.Reset() + data := struct{ a float64 }{17} + instr := &encInstr{encFloat64, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(floatResult, b.Bytes()) { + t.Errorf("float64 enc instructions: expected % x got % x", floatResult, b.Bytes()) + } + } + + // bytes == []uint8 + { + b.Reset() + data := struct{ a []byte }{[]byte("hello")} + instr := &encInstr{encUint8Array, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(bytesResult, b.Bytes()) { + t.Errorf("bytes enc instructions: expected % x got % x", bytesResult, b.Bytes()) + } + } + + // string + { + b.Reset() + data := struct{ a string }{"hello"} + instr := &encInstr{encString, 6, 0, 0} + state := newEncoderState(b) + instr.op(instr, state, unsafe.Pointer(&data)) + if !bytes.Equal(bytesResult, b.Bytes()) { + t.Errorf("string enc instructions: expected % x got % x", bytesResult, b.Bytes()) + } + } +} + +func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, p unsafe.Pointer) { + defer testError(t) + v := int(state.decodeUint()) + if v+state.fieldnum != 6 { + t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum) + } + instr.op(instr, state, decIndirect(p, instr.indir)) + state.fieldnum = 6 +} + +func newDecodeStateFromData(data []byte) *decoderState { + b := bytes.NewBuffer(data) + state := newDecodeState(b) + state.fieldnum = -1 + return state +} + +// Test instruction execution for decoding. +// Do not run the machine yet; instead do individual instructions crafted by hand. +func TestScalarDecInstructions(t *testing.T) { + ovfl := errors.New("overflow") + + // bool + { + var data struct { + a bool + } + instr := &decInstr{decBool, 6, 0, 0, ovfl} + state := newDecodeStateFromData(boolResult) + execDec("bool", instr, state, t, unsafe.Pointer(&data)) + if data.a != true { + t.Errorf("bool a = %v not true", data.a) + } + } + // int + { + var data struct { + a int + } + instr := &decInstr{decOpTable[reflect.Int], 6, 0, 0, ovfl} + state := newDecodeStateFromData(signedResult) + execDec("int", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("int a = %v not 17", data.a) + } + } + + // uint + { + var data struct { + a uint + } + instr := &decInstr{decOpTable[reflect.Uint], 6, 0, 0, ovfl} + state := newDecodeStateFromData(unsignedResult) + execDec("uint", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("uint a = %v not 17", data.a) + } + } + + // int8 + { + var data struct { + a int8 + } + instr := &decInstr{decInt8, 6, 0, 0, ovfl} + state := newDecodeStateFromData(signedResult) + execDec("int8", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("int8 a = %v not 17", data.a) + } + } + + // uint8 + { + var data struct { + a uint8 + } + instr := &decInstr{decUint8, 6, 0, 0, ovfl} + state := newDecodeStateFromData(unsignedResult) + execDec("uint8", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("uint8 a = %v not 17", data.a) + } + } + + // int16 + { + var data struct { + a int16 + } + instr := &decInstr{decInt16, 6, 0, 0, ovfl} + state := newDecodeStateFromData(signedResult) + execDec("int16", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("int16 a = %v not 17", data.a) + } + } + + // uint16 + { + var data struct { + a uint16 + } + instr := &decInstr{decUint16, 6, 0, 0, ovfl} + state := newDecodeStateFromData(unsignedResult) + execDec("uint16", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("uint16 a = %v not 17", data.a) + } + } + + // int32 + { + var data struct { + a int32 + } + instr := &decInstr{decInt32, 6, 0, 0, ovfl} + state := newDecodeStateFromData(signedResult) + execDec("int32", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("int32 a = %v not 17", data.a) + } + } + + // uint32 + { + var data struct { + a uint32 + } + instr := &decInstr{decUint32, 6, 0, 0, ovfl} + state := newDecodeStateFromData(unsignedResult) + execDec("uint32", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("uint32 a = %v not 17", data.a) + } + } + + // uintptr + { + var data struct { + a uintptr + } + instr := &decInstr{decOpTable[reflect.Uintptr], 6, 0, 0, ovfl} + state := newDecodeStateFromData(unsignedResult) + execDec("uintptr", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("uintptr a = %v not 17", data.a) + } + } + + // int64 + { + var data struct { + a int64 + } + instr := &decInstr{decInt64, 6, 0, 0, ovfl} + state := newDecodeStateFromData(signedResult) + execDec("int64", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("int64 a = %v not 17", data.a) + } + } + + // uint64 + { + var data struct { + a uint64 + } + instr := &decInstr{decUint64, 6, 0, 0, ovfl} + state := newDecodeStateFromData(unsignedResult) + execDec("uint64", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("uint64 a = %v not 17", data.a) + } + } + + // float32 + { + var data struct { + a float32 + } + instr := &decInstr{decFloat32, 6, 0, 0, ovfl} + state := newDecodeStateFromData(floatResult) + execDec("float32", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("float32 a = %v not 17", data.a) + } + } + + // float64 + { + var data struct { + a float64 + } + instr := &decInstr{decFloat64, 6, 0, 0, ovfl} + state := newDecodeStateFromData(floatResult) + execDec("float64", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17 { + t.Errorf("float64 a = %v not 17", data.a) + } + } + + // complex64 + { + var data struct { + a complex64 + } + instr := &decInstr{decOpTable[reflect.Complex64], 6, 0, 0, ovfl} + state := newDecodeStateFromData(complexResult) + execDec("complex", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17+19i { + t.Errorf("complex a = %v not 17+19i", data.a) + } + } + + // complex128 + { + var data struct { + a complex128 + } + instr := &decInstr{decOpTable[reflect.Complex128], 6, 0, 0, ovfl} + state := newDecodeStateFromData(complexResult) + execDec("complex", instr, state, t, unsafe.Pointer(&data)) + if data.a != 17+19i { + t.Errorf("complex a = %v not 17+19i", data.a) + } + } + + // bytes == []uint8 + { + var data struct { + a []byte + } + instr := &decInstr{decUint8Slice, 6, 0, 0, ovfl} + state := newDecodeStateFromData(bytesResult) + execDec("bytes", instr, state, t, unsafe.Pointer(&data)) + if string(data.a) != "hello" { + t.Errorf(`bytes a = %q not "hello"`, string(data.a)) + } + } + + // string + { + var data struct { + a string + } + instr := &decInstr{decString, 6, 0, 0, ovfl} + state := newDecodeStateFromData(bytesResult) + execDec("bytes", instr, state, t, unsafe.Pointer(&data)) + if data.a != "hello" { + t.Errorf(`bytes a = %q not "hello"`, data.a) + } + } +} + +func TestEndToEnd(t *testing.T) { + type T2 struct { + T string + } + s1 := "string1" + s2 := "string2" + type T1 struct { + A, B, C int + M map[string]*float64 + EmptyMap map[string]int // to check that we receive a non-nil map. + N *[3]float64 + Strs *[2]string + Int64s *[]int64 + RI complex64 + S string + Y []byte + T *T2 + } + pi := 3.14159 + e := 2.71828 + t1 := &T1{ + A: 17, + B: 18, + C: -5, + M: map[string]*float64{"pi": &pi, "e": &e}, + EmptyMap: make(map[string]int), + N: &[3]float64{1.5, 2.5, 3.5}, + Strs: &[2]string{s1, s2}, + Int64s: &[]int64{77, 89, 123412342134}, + RI: 17 - 23i, + S: "Now is the time", + Y: []byte("hello, sailor"), + T: &T2{"this is T2"}, + } + b := new(bytes.Buffer) + err := NewEncoder(b).Encode(t1) + if err != nil { + t.Error("encode:", err) + } + var _t1 T1 + err = NewDecoder(b).Decode(&_t1) + if err != nil { + t.Fatal("decode:", err) + } + if !reflect.DeepEqual(t1, &_t1) { + t.Errorf("encode expected %v got %v", *t1, _t1) + } + // Be absolutely sure the received map is non-nil. + if t1.EmptyMap == nil { + t.Errorf("nil map sent") + } + if _t1.EmptyMap == nil { + t.Errorf("nil map received") + } +} + +func TestOverflow(t *testing.T) { + type inputT struct { + Maxi int64 + Mini int64 + Maxu uint64 + Maxf float64 + Minf float64 + Maxc complex128 + Minc complex128 + } + var it inputT + var err error + b := new(bytes.Buffer) + enc := NewEncoder(b) + dec := NewDecoder(b) + + // int8 + b.Reset() + it = inputT{ + Maxi: math.MaxInt8 + 1, + } + type outi8 struct { + Maxi int8 + Mini int8 + } + var o1 outi8 + enc.Encode(it) + err = dec.Decode(&o1) + if err == nil || err.Error() != `value for "Maxi" out of range` { + t.Error("wrong overflow error for int8:", err) + } + it = inputT{ + Mini: math.MinInt8 - 1, + } + b.Reset() + enc.Encode(it) + err = dec.Decode(&o1) + if err == nil || err.Error() != `value for "Mini" out of range` { + t.Error("wrong underflow error for int8:", err) + } + + // int16 + b.Reset() + it = inputT{ + Maxi: math.MaxInt16 + 1, + } + type outi16 struct { + Maxi int16 + Mini int16 + } + var o2 outi16 + enc.Encode(it) + err = dec.Decode(&o2) + if err == nil || err.Error() != `value for "Maxi" out of range` { + t.Error("wrong overflow error for int16:", err) + } + it = inputT{ + Mini: math.MinInt16 - 1, + } + b.Reset() + enc.Encode(it) + err = dec.Decode(&o2) + if err == nil || err.Error() != `value for "Mini" out of range` { + t.Error("wrong underflow error for int16:", err) + } + + // int32 + b.Reset() + it = inputT{ + Maxi: math.MaxInt32 + 1, + } + type outi32 struct { + Maxi int32 + Mini int32 + } + var o3 outi32 + enc.Encode(it) + err = dec.Decode(&o3) + if err == nil || err.Error() != `value for "Maxi" out of range` { + t.Error("wrong overflow error for int32:", err) + } + it = inputT{ + Mini: math.MinInt32 - 1, + } + b.Reset() + enc.Encode(it) + err = dec.Decode(&o3) + if err == nil || err.Error() != `value for "Mini" out of range` { + t.Error("wrong underflow error for int32:", err) + } + + // uint8 + b.Reset() + it = inputT{ + Maxu: math.MaxUint8 + 1, + } + type outu8 struct { + Maxu uint8 + } + var o4 outu8 + enc.Encode(it) + err = dec.Decode(&o4) + if err == nil || err.Error() != `value for "Maxu" out of range` { + t.Error("wrong overflow error for uint8:", err) + } + + // uint16 + b.Reset() + it = inputT{ + Maxu: math.MaxUint16 + 1, + } + type outu16 struct { + Maxu uint16 + } + var o5 outu16 + enc.Encode(it) + err = dec.Decode(&o5) + if err == nil || err.Error() != `value for "Maxu" out of range` { + t.Error("wrong overflow error for uint16:", err) + } + + // uint32 + b.Reset() + it = inputT{ + Maxu: math.MaxUint32 + 1, + } + type outu32 struct { + Maxu uint32 + } + var o6 outu32 + enc.Encode(it) + err = dec.Decode(&o6) + if err == nil || err.Error() != `value for "Maxu" out of range` { + t.Error("wrong overflow error for uint32:", err) + } + + // float32 + b.Reset() + it = inputT{ + Maxf: math.MaxFloat32 * 2, + } + type outf32 struct { + Maxf float32 + Minf float32 + } + var o7 outf32 + enc.Encode(it) + err = dec.Decode(&o7) + if err == nil || err.Error() != `value for "Maxf" out of range` { + t.Error("wrong overflow error for float32:", err) + } + + // complex64 + b.Reset() + it = inputT{ + Maxc: complex(math.MaxFloat32*2, math.MaxFloat32*2), + } + type outc64 struct { + Maxc complex64 + Minc complex64 + } + var o8 outc64 + enc.Encode(it) + err = dec.Decode(&o8) + if err == nil || err.Error() != `value for "Maxc" out of range` { + t.Error("wrong overflow error for complex64:", err) + } +} + +func TestNesting(t *testing.T) { + type RT struct { + A string + Next *RT + } + rt := new(RT) + rt.A = "level1" + rt.Next = new(RT) + rt.Next.A = "level2" + b := new(bytes.Buffer) + NewEncoder(b).Encode(rt) + var drt RT + dec := NewDecoder(b) + err := dec.Decode(&drt) + if err != nil { + t.Fatal("decoder error:", err) + } + if drt.A != rt.A { + t.Errorf("nesting: encode expected %v got %v", *rt, drt) + } + if drt.Next == nil { + t.Errorf("nesting: recursion failed") + } + if drt.Next.A != rt.Next.A { + t.Errorf("nesting: encode expected %v got %v", *rt.Next, *drt.Next) + } +} + +// These three structures have the same data with different indirections +type T0 struct { + A int + B int + C int + D int +} +type T1 struct { + A int + B *int + C **int + D ***int +} +type T2 struct { + A ***int + B **int + C *int + D int +} + +func TestAutoIndirection(t *testing.T) { + // First transfer t1 into t0 + var t1 T1 + t1.A = 17 + t1.B = new(int) + *t1.B = 177 + t1.C = new(*int) + *t1.C = new(int) + **t1.C = 1777 + t1.D = new(**int) + *t1.D = new(*int) + **t1.D = new(int) + ***t1.D = 17777 + b := new(bytes.Buffer) + enc := NewEncoder(b) + enc.Encode(t1) + dec := NewDecoder(b) + var t0 T0 + dec.Decode(&t0) + if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 { + t.Errorf("t1->t0: expected {17 177 1777 17777}; got %v", t0) + } + + // Now transfer t2 into t0 + var t2 T2 + t2.D = 17777 + t2.C = new(int) + *t2.C = 1777 + t2.B = new(*int) + *t2.B = new(int) + **t2.B = 177 + t2.A = new(**int) + *t2.A = new(*int) + **t2.A = new(int) + ***t2.A = 17 + b.Reset() + enc.Encode(t2) + t0 = T0{} + dec.Decode(&t0) + if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 { + t.Errorf("t2->t0 expected {17 177 1777 17777}; got %v", t0) + } + + // Now transfer t0 into t1 + t0 = T0{17, 177, 1777, 17777} + b.Reset() + enc.Encode(t0) + t1 = T1{} + dec.Decode(&t1) + if t1.A != 17 || *t1.B != 177 || **t1.C != 1777 || ***t1.D != 17777 { + t.Errorf("t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}", t1.A, *t1.B, **t1.C, ***t1.D) + } + + // Now transfer t0 into t2 + b.Reset() + enc.Encode(t0) + t2 = T2{} + dec.Decode(&t2) + if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 { + t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D) + } + + // Now do t2 again but without pre-allocated pointers. + b.Reset() + enc.Encode(t0) + ***t2.A = 0 + **t2.B = 0 + *t2.C = 0 + t2.D = 0 + dec.Decode(&t2) + if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 { + t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D) + } +} + +type RT0 struct { + A int + B string + C float64 +} +type RT1 struct { + C float64 + B string + A int + NotSet string +} + +func TestReorderedFields(t *testing.T) { + var rt0 RT0 + rt0.A = 17 + rt0.B = "hello" + rt0.C = 3.14159 + b := new(bytes.Buffer) + NewEncoder(b).Encode(rt0) + dec := NewDecoder(b) + var rt1 RT1 + // Wire type is RT0, local type is RT1. + err := dec.Decode(&rt1) + if err != nil { + t.Fatal("decode error:", err) + } + if rt0.A != rt1.A || rt0.B != rt1.B || rt0.C != rt1.C { + t.Errorf("rt1->rt0: expected %v; got %v", rt0, rt1) + } +} + +// Like an RT0 but with fields we'll ignore on the decode side. +type IT0 struct { + A int64 + B string + Ignore_d []int + Ignore_e [3]float64 + Ignore_f bool + Ignore_g string + Ignore_h []byte + Ignore_i *RT1 + Ignore_m map[string]int + C float64 +} + +func TestIgnoredFields(t *testing.T) { + var it0 IT0 + it0.A = 17 + it0.B = "hello" + it0.C = 3.14159 + it0.Ignore_d = []int{1, 2, 3} + it0.Ignore_e[0] = 1.0 + it0.Ignore_e[1] = 2.0 + it0.Ignore_e[2] = 3.0 + it0.Ignore_f = true + it0.Ignore_g = "pay no attention" + it0.Ignore_h = []byte("to the curtain") + it0.Ignore_i = &RT1{3.1, "hi", 7, "hello"} + it0.Ignore_m = map[string]int{"one": 1, "two": 2} + + b := new(bytes.Buffer) + NewEncoder(b).Encode(it0) + dec := NewDecoder(b) + var rt1 RT1 + // Wire type is IT0, local type is RT1. + err := dec.Decode(&rt1) + if err != nil { + t.Error("error: ", err) + } + if int(it0.A) != rt1.A || it0.B != rt1.B || it0.C != rt1.C { + t.Errorf("rt0->rt1: expected %v; got %v", it0, rt1) + } +} + +func TestBadRecursiveType(t *testing.T) { + type Rec ***Rec + var rec Rec + b := new(bytes.Buffer) + err := NewEncoder(b).Encode(&rec) + if err == nil { + t.Error("expected error; got none") + } else if strings.Index(err.Error(), "recursive") < 0 { + t.Error("expected recursive type error; got", err) + } + // Can't test decode easily because we can't encode one, so we can't pass one to a Decoder. +} + +type Bad0 struct { + CH chan int + C float64 +} + +func TestInvalidField(t *testing.T) { + var bad0 Bad0 + bad0.CH = make(chan int) + b := new(bytes.Buffer) + dummyEncoder := new(Encoder) // sufficient for this purpose. + dummyEncoder.encode(b, reflect.ValueOf(&bad0), userType(reflect.TypeOf(&bad0))) + if err := dummyEncoder.err; err == nil { + t.Error("expected error; got none") + } else if strings.Index(err.Error(), "type") < 0 { + t.Error("expected type error; got", err) + } +} + +type Indirect struct { + A ***[3]int + S ***[]int + M ****map[string]int +} + +type Direct struct { + A [3]int + S []int + M map[string]int +} + +func TestIndirectSliceMapArray(t *testing.T) { + // Marshal indirect, unmarshal to direct. + i := new(Indirect) + i.A = new(**[3]int) + *i.A = new(*[3]int) + **i.A = new([3]int) + ***i.A = [3]int{1, 2, 3} + i.S = new(**[]int) + *i.S = new(*[]int) + **i.S = new([]int) + ***i.S = []int{4, 5, 6} + i.M = new(***map[string]int) + *i.M = new(**map[string]int) + **i.M = new(*map[string]int) + ***i.M = new(map[string]int) + ****i.M = map[string]int{"one": 1, "two": 2, "three": 3} + b := new(bytes.Buffer) + NewEncoder(b).Encode(i) + dec := NewDecoder(b) + var d Direct + err := dec.Decode(&d) + if err != nil { + t.Error("error: ", err) + } + if len(d.A) != 3 || d.A[0] != 1 || d.A[1] != 2 || d.A[2] != 3 { + t.Errorf("indirect to direct: d.A is %v not %v", d.A, ***i.A) + } + if len(d.S) != 3 || d.S[0] != 4 || d.S[1] != 5 || d.S[2] != 6 { + t.Errorf("indirect to direct: d.S is %v not %v", d.S, ***i.S) + } + if len(d.M) != 3 || d.M["one"] != 1 || d.M["two"] != 2 || d.M["three"] != 3 { + t.Errorf("indirect to direct: d.M is %v not %v", d.M, ***i.M) + } + // Marshal direct, unmarshal to indirect. + d.A = [3]int{11, 22, 33} + d.S = []int{44, 55, 66} + d.M = map[string]int{"four": 4, "five": 5, "six": 6} + i = new(Indirect) + b.Reset() + NewEncoder(b).Encode(d) + dec = NewDecoder(b) + err = dec.Decode(&i) + if err != nil { + t.Fatal("error: ", err) + } + if len(***i.A) != 3 || (***i.A)[0] != 11 || (***i.A)[1] != 22 || (***i.A)[2] != 33 { + t.Errorf("direct to indirect: ***i.A is %v not %v", ***i.A, d.A) + } + if len(***i.S) != 3 || (***i.S)[0] != 44 || (***i.S)[1] != 55 || (***i.S)[2] != 66 { + t.Errorf("direct to indirect: ***i.S is %v not %v", ***i.S, ***i.S) + } + if len(****i.M) != 3 || (****i.M)["four"] != 4 || (****i.M)["five"] != 5 || (****i.M)["six"] != 6 { + t.Errorf("direct to indirect: ****i.M is %v not %v", ****i.M, d.M) + } +} + +// An interface with several implementations +type Squarer interface { + Square() int +} + +type Int int + +func (i Int) Square() int { + return int(i * i) +} + +type Float float64 + +func (f Float) Square() int { + return int(f * f) +} + +type Vector []int + +func (v Vector) Square() int { + sum := 0 + for _, x := range v { + sum += x * x + } + return sum +} + +type Point struct { + X, Y int +} + +func (p Point) Square() int { + return p.X*p.X + p.Y*p.Y +} + +// A struct with interfaces in it. +type InterfaceItem struct { + I int + Sq1, Sq2, Sq3 Squarer + F float64 + Sq []Squarer +} + +// The same struct without interfaces +type NoInterfaceItem struct { + I int + F float64 +} + +func TestInterface(t *testing.T) { + iVal := Int(3) + fVal := Float(5) + // Sending a Vector will require that the receiver define a type in the middle of + // receiving the value for item2. + vVal := Vector{1, 2, 3} + b := new(bytes.Buffer) + item1 := &InterfaceItem{1, iVal, fVal, vVal, 11.5, []Squarer{iVal, fVal, nil, vVal}} + // Register the types. + Register(Int(0)) + Register(Float(0)) + Register(Vector{}) + err := NewEncoder(b).Encode(item1) + if err != nil { + t.Error("expected no encode error; got", err) + } + + item2 := InterfaceItem{} + err = NewDecoder(b).Decode(&item2) + if err != nil { + t.Fatal("decode:", err) + } + if item2.I != item1.I { + t.Error("normal int did not decode correctly") + } + if item2.Sq1 == nil || item2.Sq1.Square() != iVal.Square() { + t.Error("Int did not decode correctly") + } + if item2.Sq2 == nil || item2.Sq2.Square() != fVal.Square() { + t.Error("Float did not decode correctly") + } + if item2.Sq3 == nil || item2.Sq3.Square() != vVal.Square() { + t.Error("Vector did not decode correctly") + } + if item2.F != item1.F { + t.Error("normal float did not decode correctly") + } + // Now check that we received a slice of Squarers correctly, including a nil element + if len(item1.Sq) != len(item2.Sq) { + t.Fatalf("[]Squarer length wrong: got %d; expected %d", len(item2.Sq), len(item1.Sq)) + } + for i, v1 := range item1.Sq { + v2 := item2.Sq[i] + if v1 == nil || v2 == nil { + if v1 != nil || v2 != nil { + t.Errorf("item %d inconsistent nils", i) + } + continue + if v1.Square() != v2.Square() { + t.Errorf("item %d inconsistent values: %v %v", i, v1, v2) + } + } + } +} + +// A struct with all basic types, stored in interfaces. +type BasicInterfaceItem struct { + Int, Int8, Int16, Int32, Int64 interface{} + Uint, Uint8, Uint16, Uint32, Uint64 interface{} + Float32, Float64 interface{} + Complex64, Complex128 interface{} + Bool interface{} + String interface{} + Bytes interface{} +} + +func TestInterfaceBasic(t *testing.T) { + b := new(bytes.Buffer) + item1 := &BasicInterfaceItem{ + int(1), int8(1), int16(1), int32(1), int64(1), + uint(1), uint8(1), uint16(1), uint32(1), uint64(1), + float32(1), 1.0, + complex64(1i), complex128(1i), + true, + "hello", + []byte("sailor"), + } + err := NewEncoder(b).Encode(item1) + if err != nil { + t.Error("expected no encode error; got", err) + } + + item2 := &BasicInterfaceItem{} + err = NewDecoder(b).Decode(&item2) + if err != nil { + t.Fatal("decode:", err) + } + if !reflect.DeepEqual(item1, item2) { + t.Errorf("encode expected %v got %v", item1, item2) + } + // Hand check a couple for correct types. + if v, ok := item2.Bool.(bool); !ok || !v { + t.Error("boolean should be true") + } + if v, ok := item2.String.(string); !ok || v != item1.String.(string) { + t.Errorf("string should be %v is %v", item1.String, v) + } +} + +type String string + +type PtrInterfaceItem struct { + Str1 interface{} // basic + Str2 interface{} // derived +} + +// We'll send pointers; should receive values. +// Also check that we can register T but send *T. +func TestInterfacePointer(t *testing.T) { + b := new(bytes.Buffer) + str1 := "howdy" + str2 := String("kiddo") + item1 := &PtrInterfaceItem{ + &str1, + &str2, + } + // Register the type. + Register(str2) + err := NewEncoder(b).Encode(item1) + if err != nil { + t.Error("expected no encode error; got", err) + } + + item2 := &PtrInterfaceItem{} + err = NewDecoder(b).Decode(&item2) + if err != nil { + t.Fatal("decode:", err) + } + // Hand test for correct types and values. + if v, ok := item2.Str1.(string); !ok || v != str1 { + t.Errorf("basic string failed: %q should be %q", v, str1) + } + if v, ok := item2.Str2.(String); !ok || v != str2 { + t.Errorf("derived type String failed: %q should be %q", v, str2) + } +} + +func TestIgnoreInterface(t *testing.T) { + iVal := Int(3) + fVal := Float(5) + // Sending a Point will require that the receiver define a type in the middle of + // receiving the value for item2. + pVal := Point{2, 3} + b := new(bytes.Buffer) + item1 := &InterfaceItem{1, iVal, fVal, pVal, 11.5, nil} + // Register the types. + Register(Int(0)) + Register(Float(0)) + Register(Point{}) + err := NewEncoder(b).Encode(item1) + if err != nil { + t.Error("expected no encode error; got", err) + } + + item2 := NoInterfaceItem{} + err = NewDecoder(b).Decode(&item2) + if err != nil { + t.Fatal("decode:", err) + } + if item2.I != item1.I { + t.Error("normal int did not decode correctly") + } + if item2.F != item2.F { + t.Error("normal float did not decode correctly") + } +} + +type U struct { + A int + B string + c float64 + D uint +} + +func TestUnexportedFields(t *testing.T) { + var u0 U + u0.A = 17 + u0.B = "hello" + u0.c = 3.14159 + u0.D = 23 + b := new(bytes.Buffer) + NewEncoder(b).Encode(u0) + dec := NewDecoder(b) + var u1 U + u1.c = 1234. + err := dec.Decode(&u1) + if err != nil { + t.Fatal("decode error:", err) + } + if u0.A != u0.A || u0.B != u1.B || u0.D != u1.D { + t.Errorf("u1->u0: expected %v; got %v", u0, u1) + } + if u1.c != 1234. { + t.Error("u1.c modified") + } +} + +var singletons = []interface{}{ + true, + 7, + 3.2, + "hello", + [3]int{11, 22, 33}, + []float32{0.5, 0.25, 0.125}, + map[string]int{"one": 1, "two": 2}, +} + +func TestDebugSingleton(t *testing.T) { + if debugFunc == nil { + return + } + b := new(bytes.Buffer) + // Accumulate a number of values and print them out all at once. + for _, x := range singletons { + err := NewEncoder(b).Encode(x) + if err != nil { + t.Fatal("encode:", err) + } + } + debugFunc(b) +} + +// A type that won't be defined in the gob until we send it in an interface value. +type OnTheFly struct { + A int +} + +type DT struct { + // X OnTheFly + A int + B string + C float64 + I interface{} + J interface{} + I_nil interface{} + M map[string]int + T [3]int + S []string +} + +func TestDebugStruct(t *testing.T) { + if debugFunc == nil { + return + } + Register(OnTheFly{}) + var dt DT + dt.A = 17 + dt.B = "hello" + dt.C = 3.14159 + dt.I = 271828 + dt.J = OnTheFly{3} + dt.I_nil = nil + dt.M = map[string]int{"one": 1, "two": 2} + dt.T = [3]int{11, 22, 33} + dt.S = []string{"hi", "joe"} + b := new(bytes.Buffer) + err := NewEncoder(b).Encode(dt) + if err != nil { + t.Fatal("encode:", err) + } + debugBuffer := bytes.NewBuffer(b.Bytes()) + dt2 := &DT{} + err = NewDecoder(b).Decode(&dt2) + if err != nil { + t.Error("decode:", err) + } + debugFunc(debugBuffer) +} diff --git a/libgo/go/encoding/gob/debug.go b/libgo/go/encoding/gob/debug.go new file mode 100644 index 0000000..b21c7fa --- /dev/null +++ b/libgo/go/encoding/gob/debug.go @@ -0,0 +1,687 @@ +package gob + +// This file is not normally included in the gob package. Used only for debugging the package itself. +// Add debug.go to the files listed in the Makefile to add Debug to the gob package. +// Except for reading uints, it is an implementation of a reader that is independent of +// the one implemented by Decoder. + +import ( + "bytes" + "fmt" + "io" + "os" + "strings" + "sync" +) + +var dumpBytes = false // If true, print the remaining bytes in the input buffer at each item. + +// Init installs the debugging facility. If this file is not compiled in the +// package, the tests in codec_test.go are no-ops. +func init() { + debugFunc = Debug +} + +var ( + blanks = bytes.Repeat([]byte{' '}, 3*10) + empty = []byte(": \n") + tabs = strings.Repeat("\t", 100) +) + +// tab indents itself when printed. +type tab int + +func (t tab) String() string { + n := int(t) + if n > len(tabs) { + n = len(tabs) + } + return tabs[0:n] +} + +func (t tab) print() { + fmt.Fprint(os.Stderr, t) +} + +// A peekReader wraps an io.Reader, allowing one to peek ahead to see +// what's coming without stealing the data from the client of the Reader. +type peekReader struct { + r io.Reader + data []byte // read-ahead data +} + +// newPeekReader returns a peekReader that wraps r. +func newPeekReader(r io.Reader) *peekReader { + return &peekReader{r: r} +} + +// Read is the usual method. It will first take data that has been read ahead. +func (p *peekReader) Read(b []byte) (n int, err error) { + if len(p.data) == 0 { + return p.r.Read(b) + } + // Satisfy what's possible from the read-ahead data. + n = copy(b, p.data) + // Move data down to beginning of slice, to avoid endless growth + copy(p.data, p.data[n:]) + p.data = p.data[:len(p.data)-n] + return +} + +// peek returns as many bytes as possible from the unread +// portion of the stream, up to the length of b. +func (p *peekReader) peek(b []byte) (n int, err error) { + if len(p.data) > 0 { + n = copy(b, p.data) + if n == len(b) { + return + } + b = b[n:] + } + if len(b) == 0 { + return + } + m, e := io.ReadFull(p.r, b) + if m > 0 { + p.data = append(p.data, b[:m]...) + } + n += m + if e == io.ErrUnexpectedEOF { + // That means m > 0 but we reached EOF. If we got data + // we won't complain about not being able to peek enough. + if n > 0 { + e = nil + } else { + e = io.EOF + } + } + return n, e +} + +type debugger struct { + mutex sync.Mutex + remain int // the number of bytes known to remain in the input + remainingKnown bool // the value of 'remain' is valid + r *peekReader + wireType map[typeId]*wireType + tmp []byte // scratch space for decoding uints. +} + +// dump prints the next nBytes of the input. +// It arranges to print the output aligned from call to +// call, to make it easy to see what has been consumed. +func (deb *debugger) dump(format string, args ...interface{}) { + if !dumpBytes { + return + } + fmt.Fprintf(os.Stderr, format+" ", args...) + if !deb.remainingKnown { + return + } + if deb.remain < 0 { + fmt.Fprintf(os.Stderr, "remaining byte count is negative! %d\n", deb.remain) + return + } + data := make([]byte, deb.remain) + n, _ := deb.r.peek(data) + if n == 0 { + os.Stderr.Write(empty) + return + } + b := new(bytes.Buffer) + fmt.Fprintf(b, "[%d]{\n", deb.remain) + // Blanks until first byte + lineLength := 0 + if n := len(data); n%10 != 0 { + lineLength = 10 - n%10 + fmt.Fprintf(b, "\t%s", blanks[:lineLength*3]) + } + // 10 bytes per line + for len(data) > 0 { + if lineLength == 0 { + fmt.Fprint(b, "\t") + } + m := 10 - lineLength + lineLength = 0 + if m > len(data) { + m = len(data) + } + fmt.Fprintf(b, "% x\n", data[:m]) + data = data[m:] + } + fmt.Fprint(b, "}\n") + os.Stderr.Write(b.Bytes()) +} + +// Debug prints a human-readable representation of the gob data read from r. +// It is a no-op unless debugging was enabled when the package was built. +func Debug(r io.Reader) { + err := debug(r) + if err != nil { + fmt.Fprintf(os.Stderr, "gob debug: %s\n", err) + } +} + +// debug implements Debug, but catches panics and returns +// them as errors to be printed by Debug. +func debug(r io.Reader) (err error) { + defer catchError(&err) + fmt.Fprintln(os.Stderr, "Start of debugging") + deb := &debugger{ + r: newPeekReader(r), + wireType: make(map[typeId]*wireType), + tmp: make([]byte, 16), + } + if b, ok := r.(*bytes.Buffer); ok { + deb.remain = b.Len() + deb.remainingKnown = true + } + deb.gobStream() + return +} + +// note that we've consumed some bytes +func (deb *debugger) consumed(n int) { + if deb.remainingKnown { + deb.remain -= n + } +} + +// int64 decodes and returns the next integer, which must be present. +// Don't call this if you could be at EOF. +func (deb *debugger) int64() int64 { + return toInt(deb.uint64()) +} + +// uint64 returns and decodes the next unsigned integer, which must be present. +// Don't call this if you could be at EOF. +// TODO: handle errors better. +func (deb *debugger) uint64() uint64 { + n, w, err := decodeUintReader(deb.r, deb.tmp) + if err != nil { + errorf("debug: read error: %s", err) + } + deb.consumed(w) + return n +} + +// GobStream: +// DelimitedMessage* (until EOF) +func (deb *debugger) gobStream() { + // Make sure we're single-threaded through here. + deb.mutex.Lock() + defer deb.mutex.Unlock() + + for deb.delimitedMessage(0) { + } +} + +// DelimitedMessage: +// uint(lengthOfMessage) Message +func (deb *debugger) delimitedMessage(indent tab) bool { + for { + n := deb.loadBlock(true) + if n < 0 { + return false + } + deb.dump("Delimited message of length %d", n) + deb.message(indent) + } + return true +} + +// loadBlock preps us to read a message +// of the length specified next in the input. It returns +// the length of the block. The argument tells whether +// an EOF is acceptable now. If it is and one is found, +// the return value is negative. +func (deb *debugger) loadBlock(eofOK bool) int { + n64, w, err := decodeUintReader(deb.r, deb.tmp) // deb.uint64 will error at EOF + if err != nil { + if eofOK && err == io.EOF { + return -1 + } + errorf("debug: unexpected error: %s", err) + } + deb.consumed(w) + n := int(n64) + if n < 0 { + errorf("huge value for message length: %d", n64) + } + return int(n) +} + +// Message: +// TypeSequence TypedValue +// TypeSequence +// (TypeDefinition DelimitedTypeDefinition*)? +// DelimitedTypeDefinition: +// uint(lengthOfTypeDefinition) TypeDefinition +// TypedValue: +// int(typeId) Value +func (deb *debugger) message(indent tab) bool { + for { + // Convert the uint64 to a signed integer typeId + uid := deb.int64() + id := typeId(uid) + deb.dump("type id=%d", id) + if id < 0 { + deb.typeDefinition(indent, -id) + n := deb.loadBlock(false) + deb.dump("Message of length %d", n) + continue + } else { + deb.value(indent, id) + break + } + } + return true +} + +// Helper methods to make it easy to scan a type descriptor. + +// common returns the CommonType at the input point. +func (deb *debugger) common() CommonType { + fieldNum := -1 + name := "" + id := typeId(0) + for { + delta := deb.delta(-1) + if delta == 0 { + break + } + fieldNum += delta + switch fieldNum { + case 0: + name = deb.string() + case 1: + // Id typeId + id = deb.typeId() + default: + errorf("corrupted CommonType") + } + } + return CommonType{name, id} +} + +// uint returns the unsigned int at the input point, as a uint (not uint64). +func (deb *debugger) uint() uint { + return uint(deb.uint64()) +} + +// int returns the signed int at the input point, as an int (not int64). +func (deb *debugger) int() int { + return int(deb.int64()) +} + +// typeId returns the type id at the input point. +func (deb *debugger) typeId() typeId { + return typeId(deb.int64()) +} + +// string returns the string at the input point. +func (deb *debugger) string() string { + x := int(deb.uint64()) + b := make([]byte, x) + nb, _ := deb.r.Read(b) + if nb != x { + errorf("corrupted type") + } + deb.consumed(nb) + return string(b) +} + +// delta returns the field delta at the input point. The expect argument, +// if non-negative, identifies what the value should be. +func (deb *debugger) delta(expect int) int { + delta := int(deb.uint64()) + if delta < 0 || (expect >= 0 && delta != expect) { + errorf("decode: corrupted type: delta %d expected %d", delta, expect) + } + return delta +} + +// TypeDefinition: +// [int(-typeId) (already read)] encodingOfWireType +func (deb *debugger) typeDefinition(indent tab, id typeId) { + deb.dump("type definition for id %d", id) + // Encoding is of a wireType. Decode the structure as usual + fieldNum := -1 + wire := new(wireType) + // A wireType defines a single field. + delta := deb.delta(-1) + fieldNum += delta + switch fieldNum { + case 0: // array type, one field of {{Common}, elem, length} + // Field number 0 is CommonType + deb.delta(1) + com := deb.common() + // Field number 1 is type Id of elem + deb.delta(1) + id := deb.typeId() + // Field number 3 is length + deb.delta(1) + length := deb.int() + wire.ArrayT = &arrayType{com, id, length} + + case 1: // slice type, one field of {{Common}, elem} + // Field number 0 is CommonType + deb.delta(1) + com := deb.common() + // Field number 1 is type Id of elem + deb.delta(1) + id := deb.typeId() + wire.SliceT = &sliceType{com, id} + + case 2: // struct type, one field of {{Common}, []fieldType} + // Field number 0 is CommonType + deb.delta(1) + com := deb.common() + // Field number 1 is slice of FieldType + deb.delta(1) + numField := int(deb.uint()) + field := make([]*fieldType, numField) + for i := 0; i < numField; i++ { + field[i] = new(fieldType) + deb.delta(1) // field 0 of fieldType: name + field[i].Name = deb.string() + deb.delta(1) // field 1 of fieldType: id + field[i].Id = deb.typeId() + deb.delta(0) // end of fieldType + } + wire.StructT = &structType{com, field} + + case 3: // map type, one field of {{Common}, key, elem} + // Field number 0 is CommonType + deb.delta(1) + com := deb.common() + // Field number 1 is type Id of key + deb.delta(1) + keyId := deb.typeId() + // Field number 2 is type Id of elem + deb.delta(1) + elemId := deb.typeId() + wire.MapT = &mapType{com, keyId, elemId} + case 4: // GobEncoder type, one field of {{Common}} + // Field number 0 is CommonType + deb.delta(1) + com := deb.common() + wire.GobEncoderT = &gobEncoderType{com} + default: + errorf("bad field in type %d", fieldNum) + } + deb.printWireType(indent, wire) + deb.delta(0) // end inner type (arrayType, etc.) + deb.delta(0) // end wireType + // Remember we've seen this type. + deb.wireType[id] = wire +} + +// Value: +// SingletonValue | StructValue +func (deb *debugger) value(indent tab, id typeId) { + wire, ok := deb.wireType[id] + if ok && wire.StructT != nil { + deb.structValue(indent, id) + } else { + deb.singletonValue(indent, id) + } +} + +// SingletonValue: +// uint(0) FieldValue +func (deb *debugger) singletonValue(indent tab, id typeId) { + deb.dump("Singleton value") + // is it a builtin type? + wire := deb.wireType[id] + _, ok := builtinIdToType[id] + if !ok && wire == nil { + errorf("type id %d not defined", id) + } + m := deb.uint64() + if m != 0 { + errorf("expected zero; got %d", m) + } + deb.fieldValue(indent, id) +} + +// InterfaceValue: +// NilInterfaceValue | NonNilInterfaceValue +func (deb *debugger) interfaceValue(indent tab) { + deb.dump("Start of interface value") + if nameLen := deb.uint64(); nameLen == 0 { + deb.nilInterfaceValue(indent) + } else { + deb.nonNilInterfaceValue(indent, int(nameLen)) + } +} + +// NilInterfaceValue: +// uint(0) [already read] +func (deb *debugger) nilInterfaceValue(indent tab) int { + fmt.Fprintf(os.Stderr, "%snil interface\n", indent) + return 0 +} + +// NonNilInterfaceValue: +// ConcreteTypeName TypeSequence InterfaceContents +// ConcreteTypeName: +// uint(lengthOfName) [already read=n] name +// InterfaceContents: +// int(concreteTypeId) DelimitedValue +// DelimitedValue: +// uint(length) Value +func (deb *debugger) nonNilInterfaceValue(indent tab, nameLen int) { + // ConcreteTypeName + b := make([]byte, nameLen) + deb.r.Read(b) // TODO: CHECK THESE READS!! + deb.consumed(nameLen) + name := string(b) + + for { + id := deb.typeId() + if id < 0 { + deb.typeDefinition(indent, -id) + n := deb.loadBlock(false) + deb.dump("Nested message of length %d", n) + } else { + // DelimitedValue + x := deb.uint64() // in case we want to ignore the value; we don't. + fmt.Fprintf(os.Stderr, "%sinterface value, type %q id=%d; valueLength %d\n", indent, name, id, x) + deb.value(indent, id) + break + } + } +} + +// printCommonType prints a common type; used by printWireType. +func (deb *debugger) printCommonType(indent tab, kind string, common *CommonType) { + indent.print() + fmt.Fprintf(os.Stderr, "%s %q id=%d\n", kind, common.Name, common.Id) +} + +// printWireType prints the contents of a wireType. +func (deb *debugger) printWireType(indent tab, wire *wireType) { + fmt.Fprintf(os.Stderr, "%stype definition {\n", indent) + indent++ + switch { + case wire.ArrayT != nil: + deb.printCommonType(indent, "array", &wire.ArrayT.CommonType) + fmt.Fprintf(os.Stderr, "%slen %d\n", indent+1, wire.ArrayT.Len) + fmt.Fprintf(os.Stderr, "%selemid %d\n", indent+1, wire.ArrayT.Elem) + case wire.MapT != nil: + deb.printCommonType(indent, "map", &wire.MapT.CommonType) + fmt.Fprintf(os.Stderr, "%skey id=%d\n", indent+1, wire.MapT.Key) + fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.MapT.Elem) + case wire.SliceT != nil: + deb.printCommonType(indent, "slice", &wire.SliceT.CommonType) + fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.SliceT.Elem) + case wire.StructT != nil: + deb.printCommonType(indent, "struct", &wire.StructT.CommonType) + for i, field := range wire.StructT.Field { + fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\tid=%d\n", indent+1, i, field.Name, field.Id) + } + case wire.GobEncoderT != nil: + deb.printCommonType(indent, "GobEncoder", &wire.GobEncoderT.CommonType) + } + indent-- + fmt.Fprintf(os.Stderr, "%s}\n", indent) +} + +// fieldValue prints a value of any type, such as a struct field. +// FieldValue: +// builtinValue | ArrayValue | MapValue | SliceValue | StructValue | InterfaceValue +func (deb *debugger) fieldValue(indent tab, id typeId) { + _, ok := builtinIdToType[id] + if ok { + if id == tInterface { + deb.interfaceValue(indent) + } else { + deb.printBuiltin(indent, id) + } + return + } + wire, ok := deb.wireType[id] + if !ok { + errorf("type id %d not defined", id) + } + switch { + case wire.ArrayT != nil: + deb.arrayValue(indent, wire) + case wire.MapT != nil: + deb.mapValue(indent, wire) + case wire.SliceT != nil: + deb.sliceValue(indent, wire) + case wire.StructT != nil: + deb.structValue(indent, id) + case wire.GobEncoderT != nil: + deb.gobEncoderValue(indent, id) + default: + panic("bad wire type for field") + } +} + +// printBuiltin prints a value not of a fundamental type, that is, +// one whose type is known to gobs at bootstrap time. +func (deb *debugger) printBuiltin(indent tab, id typeId) { + switch id { + case tBool: + x := deb.int64() + if x == 0 { + fmt.Fprintf(os.Stderr, "%sfalse\n", indent) + } else { + fmt.Fprintf(os.Stderr, "%strue\n", indent) + } + case tInt: + x := deb.int64() + fmt.Fprintf(os.Stderr, "%s%d\n", indent, x) + case tUint: + x := deb.int64() + fmt.Fprintf(os.Stderr, "%s%d\n", indent, x) + case tFloat: + x := deb.uint64() + fmt.Fprintf(os.Stderr, "%s%g\n", indent, floatFromBits(x)) + case tComplex: + r := deb.uint64() + i := deb.uint64() + fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, floatFromBits(r), floatFromBits(i)) + case tBytes: + x := int(deb.uint64()) + b := make([]byte, x) + deb.r.Read(b) + deb.consumed(x) + fmt.Fprintf(os.Stderr, "%s{% x}=%q\n", indent, b, b) + case tString: + x := int(deb.uint64()) + b := make([]byte, x) + deb.r.Read(b) + deb.consumed(x) + fmt.Fprintf(os.Stderr, "%s%q\n", indent, b) + default: + panic("unknown builtin") + } +} + +// ArrayValue: +// uint(n) FieldValue*n +func (deb *debugger) arrayValue(indent tab, wire *wireType) { + elemId := wire.ArrayT.Elem + u := deb.uint64() + length := int(u) + for i := 0; i < length; i++ { + deb.fieldValue(indent, elemId) + } + if length != wire.ArrayT.Len { + fmt.Fprintf(os.Stderr, "%s(wrong length for array: %d should be %d)\n", indent, length, wire.ArrayT.Len) + } +} + +// MapValue: +// uint(n) (FieldValue FieldValue)*n [n (key, value) pairs] +func (deb *debugger) mapValue(indent tab, wire *wireType) { + keyId := wire.MapT.Key + elemId := wire.MapT.Elem + u := deb.uint64() + length := int(u) + for i := 0; i < length; i++ { + deb.fieldValue(indent+1, keyId) + deb.fieldValue(indent+1, elemId) + } +} + +// SliceValue: +// uint(n) (n FieldValue) +func (deb *debugger) sliceValue(indent tab, wire *wireType) { + elemId := wire.SliceT.Elem + u := deb.uint64() + length := int(u) + deb.dump("Start of slice of length %d", length) + + for i := 0; i < length; i++ { + deb.fieldValue(indent, elemId) + } +} + +// StructValue: +// (uint(fieldDelta) FieldValue)* +func (deb *debugger) structValue(indent tab, id typeId) { + deb.dump("Start of struct value of %q id=%d\n<<\n", id.name(), id) + fmt.Fprintf(os.Stderr, "%s%s struct {\n", indent, id.name()) + wire, ok := deb.wireType[id] + if !ok { + errorf("type id %d not defined", id) + } + strct := wire.StructT + fieldNum := -1 + indent++ + for { + delta := deb.uint64() + if delta == 0 { // struct terminator is zero delta fieldnum + break + } + fieldNum += int(delta) + if fieldNum < 0 || fieldNum >= len(strct.Field) { + deb.dump("field number out of range: prevField=%d delta=%d", fieldNum-int(delta), delta) + break + } + fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\n", indent, fieldNum, wire.StructT.Field[fieldNum].Name) + deb.fieldValue(indent+1, strct.Field[fieldNum].Id) + } + indent-- + fmt.Fprintf(os.Stderr, "%s} // end %s struct\n", indent, id.name()) + deb.dump(">> End of struct value of type %d %q", id, id.name()) +} + +// GobEncoderValue: +// uint(n) byte*n +func (deb *debugger) gobEncoderValue(indent tab, id typeId) { + len := deb.uint64() + deb.dump("GobEncoder value of %q id=%d, length %d\n", id.name(), id, len) + fmt.Fprintf(os.Stderr, "%s%s (implements GobEncoder)\n", indent, id.name()) + data := make([]byte, len) + _, err := deb.r.Read(data) + if err != nil { + errorf("gobEncoder data read: %s", err) + } + fmt.Fprintf(os.Stderr, "%s[% .2x]\n", indent+1, data) +} diff --git a/libgo/go/encoding/gob/decode.go b/libgo/go/encoding/gob/decode.go new file mode 100644 index 0000000..1515d12 --- /dev/null +++ b/libgo/go/encoding/gob/decode.go @@ -0,0 +1,1279 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +// TODO(rsc): When garbage collector changes, revisit +// the allocations in this file that use unsafe.Pointer. + +import ( + "bytes" + "errors" + "io" + "math" + "reflect" + "unsafe" +) + +var ( + errBadUint = errors.New("gob: encoded unsigned integer out of range") + errBadType = errors.New("gob: unknown type id or corrupted data") + errRange = errors.New("gob: bad data: field numbers out of bounds") +) + +// decoderState is the execution state of an instance of the decoder. A new state +// is created for nested objects. +type decoderState struct { + dec *Decoder + // The buffer is stored with an extra indirection because it may be replaced + // if we load a type during decode (when reading an interface value). + b *bytes.Buffer + fieldnum int // the last field number read. + buf []byte + next *decoderState // for free list +} + +// We pass the bytes.Buffer separately for easier testing of the infrastructure +// without requiring a full Decoder. +func (dec *Decoder) newDecoderState(buf *bytes.Buffer) *decoderState { + d := dec.freeList + if d == nil { + d = new(decoderState) + d.dec = dec + d.buf = make([]byte, uint64Size) + } else { + dec.freeList = d.next + } + d.b = buf + return d +} + +func (dec *Decoder) freeDecoderState(d *decoderState) { + d.next = dec.freeList + dec.freeList = d +} + +func overflow(name string) error { + return errors.New(`value for "` + name + `" out of range`) +} + +// decodeUintReader reads an encoded unsigned integer from an io.Reader. +// Used only by the Decoder to read the message length. +func decodeUintReader(r io.Reader, buf []byte) (x uint64, width int, err error) { + width = 1 + _, err = r.Read(buf[0:width]) + if err != nil { + return + } + b := buf[0] + if b <= 0x7f { + return uint64(b), width, nil + } + n := -int(int8(b)) + if n > uint64Size { + err = errBadUint + return + } + width, err = io.ReadFull(r, buf[0:n]) + if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return + } + // Could check that the high byte is zero but it's not worth it. + for _, b := range buf[0:width] { + x = x<<8 | uint64(b) + } + width++ // +1 for length byte + return +} + +// decodeUint reads an encoded unsigned integer from state.r. +// Does not check for overflow. +func (state *decoderState) decodeUint() (x uint64) { + b, err := state.b.ReadByte() + if err != nil { + error_(err) + } + if b <= 0x7f { + return uint64(b) + } + n := -int(int8(b)) + if n > uint64Size { + error_(errBadUint) + } + width, err := state.b.Read(state.buf[0:n]) + if err != nil { + error_(err) + } + // Don't need to check error; it's safe to loop regardless. + // Could check that the high byte is zero but it's not worth it. + for _, b := range state.buf[0:width] { + x = x<<8 | uint64(b) + } + return x +} + +// decodeInt reads an encoded signed integer from state.r. +// Does not check for overflow. +func (state *decoderState) decodeInt() int64 { + x := state.decodeUint() + if x&1 != 0 { + return ^int64(x >> 1) + } + return int64(x >> 1) +} + +// decOp is the signature of a decoding operator for a given type. +type decOp func(i *decInstr, state *decoderState, p unsafe.Pointer) + +// The 'instructions' of the decoding machine +type decInstr struct { + op decOp + field int // field number of the wire type + indir int // how many pointer indirections to reach the value in the struct + offset uintptr // offset in the structure of the field to encode + ovfl error // error message for overflow/underflow (for arrays, of the elements) +} + +// Since the encoder writes no zeros, if we arrive at a decoder we have +// a value to extract and store. The field number has already been read +// (it's how we knew to call this decoder). +// Each decoder is responsible for handling any indirections associated +// with the data structure. If any pointer so reached is nil, allocation must +// be done. + +// Walk the pointer hierarchy, allocating if we find a nil. Stop one before the end. +func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer { + for ; indir > 1; indir-- { + if *(*unsafe.Pointer)(p) == nil { + // Allocation required + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(unsafe.Pointer)) + } + p = *(*unsafe.Pointer)(p) + } + return p +} + +// ignoreUint discards a uint value with no destination. +func ignoreUint(i *decInstr, state *decoderState, p unsafe.Pointer) { + state.decodeUint() +} + +// ignoreTwoUints discards a uint value with no destination. It's used to skip +// complex values. +func ignoreTwoUints(i *decInstr, state *decoderState, p unsafe.Pointer) { + state.decodeUint() + state.decodeUint() +} + +// decBool decodes a uint and stores it as a boolean through p. +func decBool(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool)) + } + p = *(*unsafe.Pointer)(p) + } + *(*bool)(p) = state.decodeUint() != 0 +} + +// decInt8 decodes an integer and stores it as an int8 through p. +func decInt8(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8)) + } + p = *(*unsafe.Pointer)(p) + } + v := state.decodeInt() + if v < math.MinInt8 || math.MaxInt8 < v { + error_(i.ovfl) + } else { + *(*int8)(p) = int8(v) + } +} + +// decUint8 decodes an unsigned integer and stores it as a uint8 through p. +func decUint8(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8)) + } + p = *(*unsafe.Pointer)(p) + } + v := state.decodeUint() + if math.MaxUint8 < v { + error_(i.ovfl) + } else { + *(*uint8)(p) = uint8(v) + } +} + +// decInt16 decodes an integer and stores it as an int16 through p. +func decInt16(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16)) + } + p = *(*unsafe.Pointer)(p) + } + v := state.decodeInt() + if v < math.MinInt16 || math.MaxInt16 < v { + error_(i.ovfl) + } else { + *(*int16)(p) = int16(v) + } +} + +// decUint16 decodes an unsigned integer and stores it as a uint16 through p. +func decUint16(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16)) + } + p = *(*unsafe.Pointer)(p) + } + v := state.decodeUint() + if math.MaxUint16 < v { + error_(i.ovfl) + } else { + *(*uint16)(p) = uint16(v) + } +} + +// decInt32 decodes an integer and stores it as an int32 through p. +func decInt32(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32)) + } + p = *(*unsafe.Pointer)(p) + } + v := state.decodeInt() + if v < math.MinInt32 || math.MaxInt32 < v { + error_(i.ovfl) + } else { + *(*int32)(p) = int32(v) + } +} + +// decUint32 decodes an unsigned integer and stores it as a uint32 through p. +func decUint32(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32)) + } + p = *(*unsafe.Pointer)(p) + } + v := state.decodeUint() + if math.MaxUint32 < v { + error_(i.ovfl) + } else { + *(*uint32)(p) = uint32(v) + } +} + +// decInt64 decodes an integer and stores it as an int64 through p. +func decInt64(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64)) + } + p = *(*unsafe.Pointer)(p) + } + *(*int64)(p) = int64(state.decodeInt()) +} + +// decUint64 decodes an unsigned integer and stores it as a uint64 through p. +func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64)) + } + p = *(*unsafe.Pointer)(p) + } + *(*uint64)(p) = uint64(state.decodeUint()) +} + +// Floating-point numbers are transmitted as uint64s holding the bits +// of the underlying representation. They are sent byte-reversed, with +// the exponent end coming out first, so integer floating point numbers +// (for example) transmit more compactly. This routine does the +// unswizzling. +func floatFromBits(u uint64) float64 { + var v uint64 + for i := 0; i < 8; i++ { + v <<= 8 + v |= u & 0xFF + u >>= 8 + } + return math.Float64frombits(v) +} + +// storeFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point +// number, and stores it through p. It's a helper function for float32 and complex64. +func storeFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) { + v := floatFromBits(state.decodeUint()) + av := v + if av < 0 { + av = -av + } + // +Inf is OK in both 32- and 64-bit floats. Underflow is always OK. + if math.MaxFloat32 < av && av <= math.MaxFloat64 { + error_(i.ovfl) + } else { + *(*float32)(p) = float32(v) + } +} + +// decFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point +// number, and stores it through p. +func decFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32)) + } + p = *(*unsafe.Pointer)(p) + } + storeFloat32(i, state, p) +} + +// decFloat64 decodes an unsigned integer, treats it as a 64-bit floating-point +// number, and stores it through p. +func decFloat64(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64)) + } + p = *(*unsafe.Pointer)(p) + } + *(*float64)(p) = floatFromBits(uint64(state.decodeUint())) +} + +// decComplex64 decodes a pair of unsigned integers, treats them as a +// pair of floating point numbers, and stores them as a complex64 through p. +// The real part comes first. +func decComplex64(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex64)) + } + p = *(*unsafe.Pointer)(p) + } + storeFloat32(i, state, p) + storeFloat32(i, state, unsafe.Pointer(uintptr(p)+unsafe.Sizeof(float32(0)))) +} + +// decComplex128 decodes a pair of unsigned integers, treats them as a +// pair of floating point numbers, and stores them as a complex128 through p. +// The real part comes first. +func decComplex128(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex128)) + } + p = *(*unsafe.Pointer)(p) + } + real := floatFromBits(uint64(state.decodeUint())) + imag := floatFromBits(uint64(state.decodeUint())) + *(*complex128)(p) = complex(real, imag) +} + +// decUint8Slice decodes a byte slice and stores through p a slice header +// describing the data. +// uint8 slices are encoded as an unsigned count followed by the raw bytes. +func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8)) + } + p = *(*unsafe.Pointer)(p) + } + n := int(state.decodeUint()) + if n < 0 { + errorf("negative length decoding []byte") + } + slice := (*[]uint8)(p) + if cap(*slice) < n { + *slice = make([]uint8, n) + } else { + *slice = (*slice)[0:n] + } + if _, err := state.b.Read(*slice); err != nil { + errorf("error decoding []byte: %s", err) + } +} + +// decString decodes byte array and stores through p a string header +// describing the data. +// Strings are encoded as an unsigned count followed by the raw bytes. +func decString(i *decInstr, state *decoderState, p unsafe.Pointer) { + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.Pointer(new(string)) + } + p = *(*unsafe.Pointer)(p) + } + b := make([]byte, state.decodeUint()) + state.b.Read(b) + // It would be a shame to do the obvious thing here, + // *(*string)(p) = string(b) + // because we've already allocated the storage and this would + // allocate again and copy. So we do this ugly hack, which is even + // even more unsafe than it looks as it depends the memory + // representation of a string matching the beginning of the memory + // representation of a byte slice (a byte slice is longer). + *(*string)(p) = *(*string)(unsafe.Pointer(&b)) +} + +// ignoreUint8Array skips over the data for a byte slice value with no destination. +func ignoreUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) { + b := make([]byte, state.decodeUint()) + state.b.Read(b) +} + +// Execution engine + +// The encoder engine is an array of instructions indexed by field number of the incoming +// decoder. It is executed with random access according to field number. +type decEngine struct { + instr []decInstr + numInstr int // the number of active instructions +} + +// allocate makes sure storage is available for an object of underlying type rtyp +// that is indir levels of indirection through p. +func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr { + if indir == 0 { + return p + } + up := unsafe.Pointer(p) + if indir > 1 { + up = decIndirect(up, indir) + } + if *(*unsafe.Pointer)(up) == nil { + // Allocate object. + *(*unsafe.Pointer)(up) = unsafe.New(rtyp) + } + return *(*uintptr)(up) +} + +// decodeSingle decodes a top-level value that is not a struct and stores it through p. +// Such values are preceded by a zero, making them have the memory layout of a +// struct field (although with an illegal field number). +func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uintptr) (err error) { + state := dec.newDecoderState(&dec.buf) + state.fieldnum = singletonField + delta := int(state.decodeUint()) + if delta != 0 { + errorf("decode: corrupted data: non-zero delta for singleton") + } + instr := &engine.instr[singletonField] + if instr.indir != ut.indir { + return errors.New("gob: internal error: inconsistent indirection") + } + ptr := unsafe.Pointer(basep) // offset will be zero + if instr.indir > 1 { + ptr = decIndirect(ptr, instr.indir) + } + instr.op(instr, state, ptr) + dec.freeDecoderState(state) + return nil +} + +// decodeSingle decodes a top-level struct and stores it through p. +// Indir is for the value, not the type. At the time of the call it may +// differ from ut.indir, which was computed when the engine was built. +// This state cannot arise for decodeSingle, which is called directly +// from the user's value, not from the innards of an engine. +func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr, indir int) { + p = allocate(ut.base, p, indir) + state := dec.newDecoderState(&dec.buf) + state.fieldnum = -1 + basep := p + for state.b.Len() > 0 { + delta := int(state.decodeUint()) + if delta < 0 { + errorf("decode: corrupted data: negative delta") + } + if delta == 0 { // struct terminator is zero delta fieldnum + break + } + fieldnum := state.fieldnum + delta + if fieldnum >= len(engine.instr) { + error_(errRange) + break + } + instr := &engine.instr[fieldnum] + p := unsafe.Pointer(basep + instr.offset) + if instr.indir > 1 { + p = decIndirect(p, instr.indir) + } + instr.op(instr, state, p) + state.fieldnum = fieldnum + } + dec.freeDecoderState(state) +} + +// ignoreStruct discards the data for a struct with no destination. +func (dec *Decoder) ignoreStruct(engine *decEngine) { + state := dec.newDecoderState(&dec.buf) + state.fieldnum = -1 + for state.b.Len() > 0 { + delta := int(state.decodeUint()) + if delta < 0 { + errorf("ignore decode: corrupted data: negative delta") + } + if delta == 0 { // struct terminator is zero delta fieldnum + break + } + fieldnum := state.fieldnum + delta + if fieldnum >= len(engine.instr) { + error_(errRange) + } + instr := &engine.instr[fieldnum] + instr.op(instr, state, unsafe.Pointer(nil)) + state.fieldnum = fieldnum + } + dec.freeDecoderState(state) +} + +// ignoreSingle discards the data for a top-level non-struct value with no +// destination. It's used when calling Decode with a nil value. +func (dec *Decoder) ignoreSingle(engine *decEngine) { + state := dec.newDecoderState(&dec.buf) + state.fieldnum = singletonField + delta := int(state.decodeUint()) + if delta != 0 { + errorf("decode: corrupted data: non-zero delta for singleton") + } + instr := &engine.instr[singletonField] + instr.op(instr, state, unsafe.Pointer(nil)) + dec.freeDecoderState(state) +} + +// decodeArrayHelper does the work for decoding arrays and slices. +func (dec *Decoder) decodeArrayHelper(state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) { + instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl} + for i := 0; i < length; i++ { + up := unsafe.Pointer(p) + if elemIndir > 1 { + up = decIndirect(up, elemIndir) + } + elemOp(instr, state, up) + p += uintptr(elemWid) + } +} + +// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element. +// The length is an unsigned integer preceding the elements. Even though the length is redundant +// (it's part of the type), it's a useful check and is included in the encoding. +func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) { + if indir > 0 { + p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect + } + if n := state.decodeUint(); n != uint64(length) { + errorf("length mismatch in decodeArray") + } + dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl) +} + +// decodeIntoValue is a helper for map decoding. Since maps are decoded using reflection, +// unlike the other items we can't use a pointer directly. +func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl error) reflect.Value { + instr := &decInstr{op, 0, indir, 0, ovfl} + up := unsafe.Pointer(unsafeAddr(v)) + if indir > 1 { + up = decIndirect(up, indir) + } + op(instr, state, up) + return v +} + +// decodeMap decodes a map and stores its header through p. +// Maps are encoded as a length followed by key:value pairs. +// Because the internals of maps are not visible to us, we must +// use reflection rather than pointer magic. +func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) { + if indir > 0 { + p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect + } + up := unsafe.Pointer(p) + if *(*unsafe.Pointer)(up) == nil { // maps are represented as a pointer in the runtime + // Allocate map. + *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.MakeMap(mtyp).Pointer()) + } + // Maps cannot be accessed by moving addresses around the way + // that slices etc. can. We must recover a full reflection value for + // the iteration. + v := reflect.ValueOf(unsafe.Unreflect(mtyp, unsafe.Pointer(p))) + n := int(state.decodeUint()) + for i := 0; i < n; i++ { + key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl) + elem := decodeIntoValue(state, elemOp, elemIndir, allocValue(mtyp.Elem()), ovfl) + v.SetMapIndex(key, elem) + } +} + +// ignoreArrayHelper does the work for discarding arrays and slices. +func (dec *Decoder) ignoreArrayHelper(state *decoderState, elemOp decOp, length int) { + instr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")} + for i := 0; i < length; i++ { + elemOp(instr, state, nil) + } +} + +// ignoreArray discards the data for an array value with no destination. +func (dec *Decoder) ignoreArray(state *decoderState, elemOp decOp, length int) { + if n := state.decodeUint(); n != uint64(length) { + errorf("length mismatch in ignoreArray") + } + dec.ignoreArrayHelper(state, elemOp, length) +} + +// ignoreMap discards the data for a map value with no destination. +func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) { + n := int(state.decodeUint()) + keyInstr := &decInstr{keyOp, 0, 0, 0, errors.New("no error")} + elemInstr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")} + for i := 0; i < n; i++ { + keyOp(keyInstr, state, nil) + elemOp(elemInstr, state, nil) + } +} + +// decodeSlice decodes a slice and stores the slice header through p. +// Slices are encoded as an unsigned length followed by the elements. +func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) { + n := int(uintptr(state.decodeUint())) + if indir > 0 { + up := unsafe.Pointer(p) + if *(*unsafe.Pointer)(up) == nil { + // Allocate the slice header. + *(*unsafe.Pointer)(up) = unsafe.Pointer(new([]unsafe.Pointer)) + } + p = *(*uintptr)(up) + } + // Allocate storage for the slice elements, that is, the underlying array, + // if the existing slice does not have the capacity. + // Always write a header at p. + hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p)) + if hdrp.Cap < n { + hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n)) + hdrp.Cap = n + } + hdrp.Len = n + dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl) +} + +// ignoreSlice skips over the data for a slice value with no destination. +func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) { + dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint())) +} + +// setInterfaceValue sets an interface value to a concrete value, +// but first it checks that the assignment will succeed. +func setInterfaceValue(ivalue reflect.Value, value reflect.Value) { + if !value.Type().AssignableTo(ivalue.Type()) { + errorf("cannot assign value of type %s to %s", value.Type(), ivalue.Type()) + } + ivalue.Set(value) +} + +// decodeInterface decodes an interface value and stores it through p. +// Interfaces are encoded as the name of a concrete type followed by a value. +// If the name is empty, the value is nil and no value is sent. +func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p uintptr, indir int) { + // Create a writable interface reflect.Value. We need one even for the nil case. + ivalue := allocValue(ityp) + // Read the name of the concrete type. + b := make([]byte, state.decodeUint()) + state.b.Read(b) + name := string(b) + if name == "" { + // Copy the representation of the nil interface value to the target. + // This is horribly unsafe and special. + *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData() + return + } + // The concrete type must be registered. + typ, ok := nameToConcreteType[name] + if !ok { + errorf("name not registered for interface: %q", name) + } + // Read the type id of the concrete value. + concreteId := dec.decodeTypeSequence(true) + if concreteId < 0 { + error_(dec.err) + } + // Byte count of value is next; we don't care what it is (it's there + // in case we want to ignore the value by skipping it completely). + state.decodeUint() + // Read the concrete value. + value := allocValue(typ) + dec.decodeValue(concreteId, value) + if dec.err != nil { + error_(dec.err) + } + // Allocate the destination interface value. + if indir > 0 { + p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect + } + // Assign the concrete value to the interface. + // Tread carefully; it might not satisfy the interface. + setInterfaceValue(ivalue, value) + // Copy the representation of the interface value to the target. + // This is horribly unsafe and special. + *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData() +} + +// ignoreInterface discards the data for an interface value with no destination. +func (dec *Decoder) ignoreInterface(state *decoderState) { + // Read the name of the concrete type. + b := make([]byte, state.decodeUint()) + _, err := state.b.Read(b) + if err != nil { + error_(err) + } + id := dec.decodeTypeSequence(true) + if id < 0 { + error_(dec.err) + } + // At this point, the decoder buffer contains a delimited value. Just toss it. + state.b.Next(int(state.decodeUint())) +} + +// decodeGobDecoder decodes something implementing the GobDecoder interface. +// The data is encoded as a byte slice. +func (dec *Decoder) decodeGobDecoder(state *decoderState, v reflect.Value) { + // Read the bytes for the value. + b := make([]byte, state.decodeUint()) + _, err := state.b.Read(b) + if err != nil { + error_(err) + } + // We know it's a GobDecoder, so just call the method directly. + err = v.Interface().(GobDecoder).GobDecode(b) + if err != nil { + error_(err) + } +} + +// ignoreGobDecoder discards the data for a GobDecoder value with no destination. +func (dec *Decoder) ignoreGobDecoder(state *decoderState) { + // Read the bytes for the value. + b := make([]byte, state.decodeUint()) + _, err := state.b.Read(b) + if err != nil { + error_(err) + } +} + +// Index by Go types. +var decOpTable = [...]decOp{ + reflect.Bool: decBool, + reflect.Int8: decInt8, + reflect.Int16: decInt16, + reflect.Int32: decInt32, + reflect.Int64: decInt64, + reflect.Uint8: decUint8, + reflect.Uint16: decUint16, + reflect.Uint32: decUint32, + reflect.Uint64: decUint64, + reflect.Float32: decFloat32, + reflect.Float64: decFloat64, + reflect.Complex64: decComplex64, + reflect.Complex128: decComplex128, + reflect.String: decString, +} + +// Indexed by gob types. tComplex will be added during type.init(). +var decIgnoreOpMap = map[typeId]decOp{ + tBool: ignoreUint, + tInt: ignoreUint, + tUint: ignoreUint, + tFloat: ignoreUint, + tBytes: ignoreUint8Array, + tString: ignoreUint8Array, + tComplex: ignoreTwoUints, +} + +// decOpFor returns the decoding op for the base type under rt and +// the indirection count to reach it. +func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) (*decOp, int) { + ut := userType(rt) + // If the type implements GobEncoder, we handle it without further processing. + if ut.isGobDecoder { + return dec.gobDecodeOpFor(ut) + } + // If this type is already in progress, it's a recursive type (e.g. map[string]*T). + // Return the pointer to the op we're already building. + if opPtr := inProgress[rt]; opPtr != nil { + return opPtr, ut.indir + } + typ := ut.base + indir := ut.indir + var op decOp + k := typ.Kind() + if int(k) < len(decOpTable) { + op = decOpTable[k] + } + if op == nil { + inProgress[rt] = &op + // Special cases + switch t := typ; t.Kind() { + case reflect.Array: + name = "element of " + name + elemId := dec.wireType[wireId].ArrayT.Elem + elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress) + ovfl := overflow(name) + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + state.dec.decodeArray(t, state, uintptr(p), *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl) + } + + case reflect.Map: + name = "element of " + name + keyId := dec.wireType[wireId].MapT.Key + elemId := dec.wireType[wireId].MapT.Elem + keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), name, inProgress) + elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress) + ovfl := overflow(name) + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + up := unsafe.Pointer(p) + state.dec.decodeMap(t, state, uintptr(up), *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl) + } + + case reflect.Slice: + name = "element of " + name + if t.Elem().Kind() == reflect.Uint8 { + op = decUint8Slice + break + } + var elemId typeId + if tt, ok := builtinIdToType[wireId]; ok { + elemId = tt.(*sliceType).Elem + } else { + elemId = dec.wireType[wireId].SliceT.Elem + } + elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress) + ovfl := overflow(name) + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + state.dec.decodeSlice(t, state, uintptr(p), *elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl) + } + + case reflect.Struct: + // Generate a closure that calls out to the engine for the nested type. + enginePtr, err := dec.getDecEnginePtr(wireId, userType(typ)) + if err != nil { + error_(err) + } + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + // indirect through enginePtr to delay evaluation for recursive structs. + dec.decodeStruct(*enginePtr, userType(typ), uintptr(p), i.indir) + } + case reflect.Interface: + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + state.dec.decodeInterface(t, state, uintptr(p), i.indir) + } + } + } + if op == nil { + errorf("decode can't handle type %s", rt) + } + return &op, indir +} + +// decIgnoreOpFor returns the decoding op for a field that has no destination. +func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp { + op, ok := decIgnoreOpMap[wireId] + if !ok { + if wireId == tInterface { + // Special case because it's a method: the ignored item might + // define types and we need to record their state in the decoder. + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + state.dec.ignoreInterface(state) + } + return op + } + // Special cases + wire := dec.wireType[wireId] + switch { + case wire == nil: + errorf("bad data: undefined type %s", wireId.string()) + case wire.ArrayT != nil: + elemId := wire.ArrayT.Elem + elemOp := dec.decIgnoreOpFor(elemId) + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len) + } + + case wire.MapT != nil: + keyId := dec.wireType[wireId].MapT.Key + elemId := dec.wireType[wireId].MapT.Elem + keyOp := dec.decIgnoreOpFor(keyId) + elemOp := dec.decIgnoreOpFor(elemId) + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + state.dec.ignoreMap(state, keyOp, elemOp) + } + + case wire.SliceT != nil: + elemId := wire.SliceT.Elem + elemOp := dec.decIgnoreOpFor(elemId) + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + state.dec.ignoreSlice(state, elemOp) + } + + case wire.StructT != nil: + // Generate a closure that calls out to the engine for the nested type. + enginePtr, err := dec.getIgnoreEnginePtr(wireId) + if err != nil { + error_(err) + } + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + // indirect through enginePtr to delay evaluation for recursive structs + state.dec.ignoreStruct(*enginePtr) + } + + case wire.GobEncoderT != nil: + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + state.dec.ignoreGobDecoder(state) + } + } + } + if op == nil { + errorf("bad data: ignore can't handle type %s", wireId.string()) + } + return op +} + +// gobDecodeOpFor returns the op for a type that is known to implement +// GobDecoder. +func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) { + rcvrType := ut.user + if ut.decIndir == -1 { + rcvrType = reflect.PtrTo(rcvrType) + } else if ut.decIndir > 0 { + for i := int8(0); i < ut.decIndir; i++ { + rcvrType = rcvrType.Elem() + } + } + var op decOp + op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + // Caller has gotten us to within one indirection of our value. + if i.indir > 0 { + if *(*unsafe.Pointer)(p) == nil { + *(*unsafe.Pointer)(p) = unsafe.New(ut.base) + } + } + // Now p is a pointer to the base type. Do we need to climb out to + // get to the receiver type? + var v reflect.Value + if ut.decIndir == -1 { + v = reflect.ValueOf(unsafe.Unreflect(rcvrType, unsafe.Pointer(&p))) + } else { + v = reflect.ValueOf(unsafe.Unreflect(rcvrType, p)) + } + state.dec.decodeGobDecoder(state, v) + } + return &op, int(ut.indir) + +} + +// compatibleType asks: Are these two gob Types compatible? +// Answers the question for basic types, arrays, maps and slices, plus +// GobEncoder/Decoder pairs. +// Structs are considered ok; fields will be checked later. +func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId, inProgress map[reflect.Type]typeId) bool { + if rhs, ok := inProgress[fr]; ok { + return rhs == fw + } + inProgress[fr] = fw + ut := userType(fr) + wire, ok := dec.wireType[fw] + // If fr is a GobDecoder, the wire type must be GobEncoder. + // And if fr is not a GobDecoder, the wire type must not be either. + if ut.isGobDecoder != (ok && wire.GobEncoderT != nil) { // the parentheses look odd but are correct. + return false + } + if ut.isGobDecoder { // This test trumps all others. + return true + } + switch t := ut.base; t.Kind() { + default: + // chan, etc: cannot handle. + return false + case reflect.Bool: + return fw == tBool + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return fw == tInt + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return fw == tUint + case reflect.Float32, reflect.Float64: + return fw == tFloat + case reflect.Complex64, reflect.Complex128: + return fw == tComplex + case reflect.String: + return fw == tString + case reflect.Interface: + return fw == tInterface + case reflect.Array: + if !ok || wire.ArrayT == nil { + return false + } + array := wire.ArrayT + return t.Len() == array.Len && dec.compatibleType(t.Elem(), array.Elem, inProgress) + case reflect.Map: + if !ok || wire.MapT == nil { + return false + } + MapType := wire.MapT + return dec.compatibleType(t.Key(), MapType.Key, inProgress) && dec.compatibleType(t.Elem(), MapType.Elem, inProgress) + case reflect.Slice: + // Is it an array of bytes? + if t.Elem().Kind() == reflect.Uint8 { + return fw == tBytes + } + // Extract and compare element types. + var sw *sliceType + if tt, ok := builtinIdToType[fw]; ok { + sw = tt.(*sliceType) + } else { + sw = dec.wireType[fw].SliceT + } + elem := userType(t.Elem()).base + return sw != nil && dec.compatibleType(elem, sw.Elem, inProgress) + case reflect.Struct: + return true + } + return true +} + +// typeString returns a human-readable description of the type identified by remoteId. +func (dec *Decoder) typeString(remoteId typeId) string { + if t := idToType[remoteId]; t != nil { + // globally known type. + return t.string() + } + return dec.wireType[remoteId].string() +} + +// compileSingle compiles the decoder engine for a non-struct top-level value, including +// GobDecoders. +func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) { + rt := ut.user + engine = new(decEngine) + engine.instr = make([]decInstr, 1) // one item + name := rt.String() // best we can do + if !dec.compatibleType(rt, remoteId, make(map[reflect.Type]typeId)) { + return nil, errors.New("gob: wrong type received for local value " + name + ": " + dec.typeString(remoteId)) + } + op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp)) + ovfl := errors.New(`value for "` + name + `" out of range`) + engine.instr[singletonField] = decInstr{*op, singletonField, indir, 0, ovfl} + engine.numInstr = 1 + return +} + +// compileIgnoreSingle compiles the decoder engine for a non-struct top-level value that will be discarded. +func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err error) { + engine = new(decEngine) + engine.instr = make([]decInstr, 1) // one item + op := dec.decIgnoreOpFor(remoteId) + ovfl := overflow(dec.typeString(remoteId)) + engine.instr[0] = decInstr{op, 0, 0, 0, ovfl} + engine.numInstr = 1 + return +} + +// compileDec compiles the decoder engine for a value. If the value is not a struct, +// it calls out to compileSingle. +func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) { + rt := ut.base + srt := rt + if srt.Kind() != reflect.Struct || + ut.isGobDecoder { + return dec.compileSingle(remoteId, ut) + } + var wireStruct *structType + // Builtin types can come from global pool; the rest must be defined by the decoder. + // Also we know we're decoding a struct now, so the client must have sent one. + if t, ok := builtinIdToType[remoteId]; ok { + wireStruct, _ = t.(*structType) + } else { + wire := dec.wireType[remoteId] + if wire == nil { + error_(errBadType) + } + wireStruct = wire.StructT + } + if wireStruct == nil { + errorf("type mismatch in decoder: want struct type %s; got non-struct", rt) + } + engine = new(decEngine) + engine.instr = make([]decInstr, len(wireStruct.Field)) + seen := make(map[reflect.Type]*decOp) + // Loop over the fields of the wire type. + for fieldnum := 0; fieldnum < len(wireStruct.Field); fieldnum++ { + wireField := wireStruct.Field[fieldnum] + if wireField.Name == "" { + errorf("empty name for remote field of type %s", wireStruct.Name) + } + ovfl := overflow(wireField.Name) + // Find the field of the local type with the same name. + localField, present := srt.FieldByName(wireField.Name) + // TODO(r): anonymous names + if !present || !isExported(wireField.Name) { + op := dec.decIgnoreOpFor(wireField.Id) + engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl} + continue + } + if !dec.compatibleType(localField.Type, wireField.Id, make(map[reflect.Type]typeId)) { + errorf("wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name) + } + op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen) + engine.instr[fieldnum] = decInstr{*op, fieldnum, indir, uintptr(localField.Offset), ovfl} + engine.numInstr++ + } + return +} + +// getDecEnginePtr returns the engine for the specified type. +func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePtr **decEngine, err error) { + rt := ut.base + decoderMap, ok := dec.decoderCache[rt] + if !ok { + decoderMap = make(map[typeId]**decEngine) + dec.decoderCache[rt] = decoderMap + } + if enginePtr, ok = decoderMap[remoteId]; !ok { + // To handle recursive types, mark this engine as underway before compiling. + enginePtr = new(*decEngine) + decoderMap[remoteId] = enginePtr + *enginePtr, err = dec.compileDec(remoteId, ut) + if err != nil { + delete(decoderMap, remoteId) + } + } + return +} + +// emptyStruct is the type we compile into when ignoring a struct value. +type emptyStruct struct{} + +var emptyStructType = reflect.TypeOf(emptyStruct{}) + +// getDecEnginePtr returns the engine for the specified type when the value is to be discarded. +func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, err error) { + var ok bool + if enginePtr, ok = dec.ignorerCache[wireId]; !ok { + // To handle recursive types, mark this engine as underway before compiling. + enginePtr = new(*decEngine) + dec.ignorerCache[wireId] = enginePtr + wire := dec.wireType[wireId] + if wire != nil && wire.StructT != nil { + *enginePtr, err = dec.compileDec(wireId, userType(emptyStructType)) + } else { + *enginePtr, err = dec.compileIgnoreSingle(wireId) + } + if err != nil { + delete(dec.ignorerCache, wireId) + } + } + return +} + +// decodeValue decodes the data stream representing a value and stores it in val. +func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) { + defer catchError(&dec.err) + // If the value is nil, it means we should just ignore this item. + if !val.IsValid() { + dec.decodeIgnoredValue(wireId) + return + } + // Dereference down to the underlying type. + ut := userType(val.Type()) + base := ut.base + var enginePtr **decEngine + enginePtr, dec.err = dec.getDecEnginePtr(wireId, ut) + if dec.err != nil { + return + } + engine := *enginePtr + if st := base; st.Kind() == reflect.Struct && !ut.isGobDecoder { + if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 { + name := base.Name() + errorf("type mismatch: no fields matched compiling decoder for %s", name) + } + dec.decodeStruct(engine, ut, uintptr(unsafeAddr(val)), ut.indir) + } else { + dec.decodeSingle(engine, ut, uintptr(unsafeAddr(val))) + } +} + +// decodeIgnoredValue decodes the data stream representing a value of the specified type and discards it. +func (dec *Decoder) decodeIgnoredValue(wireId typeId) { + var enginePtr **decEngine + enginePtr, dec.err = dec.getIgnoreEnginePtr(wireId) + if dec.err != nil { + return + } + wire := dec.wireType[wireId] + if wire != nil && wire.StructT != nil { + dec.ignoreStruct(*enginePtr) + } else { + dec.ignoreSingle(*enginePtr) + } +} + +func init() { + var iop, uop decOp + switch reflect.TypeOf(int(0)).Bits() { + case 32: + iop = decInt32 + uop = decUint32 + case 64: + iop = decInt64 + uop = decUint64 + default: + panic("gob: unknown size of int/uint") + } + decOpTable[reflect.Int] = iop + decOpTable[reflect.Uint] = uop + + // Finally uintptr + switch reflect.TypeOf(uintptr(0)).Bits() { + case 32: + uop = decUint32 + case 64: + uop = decUint64 + default: + panic("gob: unknown size of uintptr") + } + decOpTable[reflect.Uintptr] = uop +} + +// Gob assumes it can call UnsafeAddr on any Value +// in order to get a pointer it can copy data from. +// Values that have just been created and do not point +// into existing structs or slices cannot be addressed, +// so simulate it by returning a pointer to a copy. +// Each call allocates once. +func unsafeAddr(v reflect.Value) uintptr { + if v.CanAddr() { + return v.UnsafeAddr() + } + x := reflect.New(v.Type()).Elem() + x.Set(v) + return x.UnsafeAddr() +} + +// Gob depends on being able to take the address +// of zeroed Values it creates, so use this wrapper instead +// of the standard reflect.Zero. +// Each call allocates once. +func allocValue(t reflect.Type) reflect.Value { + return reflect.New(t).Elem() +} diff --git a/libgo/go/encoding/gob/decoder.go b/libgo/go/encoding/gob/decoder.go new file mode 100644 index 0000000..5e684d3 --- /dev/null +++ b/libgo/go/encoding/gob/decoder.go @@ -0,0 +1,214 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import ( + "bufio" + "bytes" + "errors" + "io" + "reflect" + "sync" +) + +// A Decoder manages the receipt of type and data information read from the +// remote side of a connection. +type Decoder struct { + mutex sync.Mutex // each item must be received atomically + r io.Reader // source of the data + buf bytes.Buffer // buffer for more efficient i/o from r + wireType map[typeId]*wireType // map from remote ID to local description + decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines + ignorerCache map[typeId]**decEngine // ditto for ignored objects + freeList *decoderState // list of free decoderStates; avoids reallocation + countBuf []byte // used for decoding integers while parsing messages + tmp []byte // temporary storage for i/o; saves reallocating + err error +} + +// NewDecoder returns a new decoder that reads from the io.Reader. +// If r does not also implement io.ByteReader, it will be wrapped in a +// bufio.Reader. +func NewDecoder(r io.Reader) *Decoder { + dec := new(Decoder) + // We use the ability to read bytes as a plausible surrogate for buffering. + if _, ok := r.(io.ByteReader); !ok { + r = bufio.NewReader(r) + } + dec.r = r + dec.wireType = make(map[typeId]*wireType) + dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine) + dec.ignorerCache = make(map[typeId]**decEngine) + dec.countBuf = make([]byte, 9) // counts may be uint64s (unlikely!), require 9 bytes + + return dec +} + +// recvType loads the definition of a type. +func (dec *Decoder) recvType(id typeId) { + // Have we already seen this type? That's an error + if id < firstUserId || dec.wireType[id] != nil { + dec.err = errors.New("gob: duplicate type received") + return + } + + // Type: + wire := new(wireType) + dec.decodeValue(tWireType, reflect.ValueOf(wire)) + if dec.err != nil { + return + } + // Remember we've seen this type. + dec.wireType[id] = wire +} + +var errBadCount = errors.New("invalid message length") + +// recvMessage reads the next count-delimited item from the input. It is the converse +// of Encoder.writeMessage. It returns false on EOF or other error reading the message. +func (dec *Decoder) recvMessage() bool { + // Read a count. + nbytes, _, err := decodeUintReader(dec.r, dec.countBuf) + if err != nil { + dec.err = err + return false + } + if nbytes >= 1<<31 { + dec.err = errBadCount + return false + } + dec.readMessage(int(nbytes)) + return dec.err == nil +} + +// readMessage reads the next nbytes bytes from the input. +func (dec *Decoder) readMessage(nbytes int) { + // Allocate the buffer. + if cap(dec.tmp) < nbytes { + dec.tmp = make([]byte, nbytes+100) // room to grow + } + dec.tmp = dec.tmp[:nbytes] + + // Read the data + _, dec.err = io.ReadFull(dec.r, dec.tmp) + if dec.err != nil { + if dec.err == io.EOF { + dec.err = io.ErrUnexpectedEOF + } + return + } + dec.buf.Write(dec.tmp) +} + +// toInt turns an encoded uint64 into an int, according to the marshaling rules. +func toInt(x uint64) int64 { + i := int64(x >> 1) + if x&1 != 0 { + i = ^i + } + return i +} + +func (dec *Decoder) nextInt() int64 { + n, _, err := decodeUintReader(&dec.buf, dec.countBuf) + if err != nil { + dec.err = err + } + return toInt(n) +} + +func (dec *Decoder) nextUint() uint64 { + n, _, err := decodeUintReader(&dec.buf, dec.countBuf) + if err != nil { + dec.err = err + } + return n +} + +// decodeTypeSequence parses: +// TypeSequence +// (TypeDefinition DelimitedTypeDefinition*)? +// and returns the type id of the next value. It returns -1 at +// EOF. Upon return, the remainder of dec.buf is the value to be +// decoded. If this is an interface value, it can be ignored by +// simply resetting that buffer. +func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId { + for dec.err == nil { + if dec.buf.Len() == 0 { + if !dec.recvMessage() { + break + } + } + // Receive a type id. + id := typeId(dec.nextInt()) + if id >= 0 { + // Value follows. + return id + } + // Type definition for (-id) follows. + dec.recvType(-id) + // When decoding an interface, after a type there may be a + // DelimitedValue still in the buffer. Skip its count. + // (Alternatively, the buffer is empty and the byte count + // will be absorbed by recvMessage.) + if dec.buf.Len() > 0 { + if !isInterface { + dec.err = errors.New("extra data in buffer") + break + } + dec.nextUint() + } + } + return -1 +} + +// Decode reads the next value from the connection and stores +// it in the data represented by the empty interface value. +// If e is nil, the value will be discarded. Otherwise, +// the value underlying e must be a pointer to the +// correct type for the next data item received. +func (dec *Decoder) Decode(e interface{}) error { + if e == nil { + return dec.DecodeValue(reflect.Value{}) + } + value := reflect.ValueOf(e) + // If e represents a value as opposed to a pointer, the answer won't + // get back to the caller. Make sure it's a pointer. + if value.Type().Kind() != reflect.Ptr { + dec.err = errors.New("gob: attempt to decode into a non-pointer") + return dec.err + } + return dec.DecodeValue(value) +} + +// DecodeValue reads the next value from the connection. +// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value. +// Otherwise, it stores the value into v. In that case, v must represent +// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet()) +func (dec *Decoder) DecodeValue(v reflect.Value) error { + if v.IsValid() { + if v.Kind() == reflect.Ptr && !v.IsNil() { + // That's okay, we'll store through the pointer. + } else if !v.CanSet() { + return errors.New("gob: DecodeValue of unassignable value") + } + } + // Make sure we're single-threaded through here. + dec.mutex.Lock() + defer dec.mutex.Unlock() + + dec.buf.Reset() // In case data lingers from previous invocation. + dec.err = nil + id := dec.decodeTypeSequence(false) + if dec.err == nil { + dec.decodeValue(id, v) + } + return dec.err +} + +// If debug.go is compiled into the program , debugFunc prints a human-readable +// representation of the gob data read from r by calling that file's Debug function. +// Otherwise it is nil. +var debugFunc func(io.Reader) diff --git a/libgo/go/encoding/gob/doc.go b/libgo/go/encoding/gob/doc.go new file mode 100644 index 0000000..05ebef1 --- /dev/null +++ b/libgo/go/encoding/gob/doc.go @@ -0,0 +1,366 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package gob manages streams of gobs - binary values exchanged between an +Encoder (transmitter) and a Decoder (receiver). A typical use is transporting +arguments and results of remote procedure calls (RPCs) such as those provided by +package "rpc". + +A stream of gobs is self-describing. Each data item in the stream is preceded by +a specification of its type, expressed in terms of a small set of predefined +types. Pointers are not transmitted, but the things they point to are +transmitted; that is, the values are flattened. Recursive types work fine, but +recursive values (data with cycles) are problematic. This may change. + +To use gobs, create an Encoder and present it with a series of data items as +values or addresses that can be dereferenced to values. The Encoder makes sure +all type information is sent before it is needed. At the receive side, a +Decoder retrieves values from the encoded stream and unpacks them into local +variables. + +The source and destination values/types need not correspond exactly. For structs, +fields (identified by name) that are in the source but absent from the receiving +variable will be ignored. Fields that are in the receiving variable but missing +from the transmitted type or value will be ignored in the destination. If a field +with the same name is present in both, their types must be compatible. Both the +receiver and transmitter will do all necessary indirection and dereferencing to +convert between gobs and actual Go values. For instance, a gob type that is +schematically, + + struct { A, B int } + +can be sent from or received into any of these Go types: + + struct { A, B int } // the same + *struct { A, B int } // extra indirection of the struct + struct { *A, **B int } // extra indirection of the fields + struct { A, B int64 } // different concrete value type; see below + +It may also be received into any of these: + + struct { A, B int } // the same + struct { B, A int } // ordering doesn't matter; matching is by name + struct { A, B, C int } // extra field (C) ignored + struct { B int } // missing field (A) ignored; data will be dropped + struct { B, C int } // missing field (A) ignored; extra field (C) ignored. + +Attempting to receive into these types will draw a decode error: + + struct { A int; B uint } // change of signedness for B + struct { A int; B float } // change of type for B + struct { } // no field names in common + struct { C, D int } // no field names in common + +Integers are transmitted two ways: arbitrary precision signed integers or +arbitrary precision unsigned integers. There is no int8, int16 etc. +discrimination in the gob format; there are only signed and unsigned integers. As +described below, the transmitter sends the value in a variable-length encoding; +the receiver accepts the value and stores it in the destination variable. +Floating-point numbers are always sent using IEEE-754 64-bit precision (see +below). + +Signed integers may be received into any signed integer variable: int, int16, etc.; +unsigned integers may be received into any unsigned integer variable; and floating +point values may be received into any floating point variable. However, +the destination variable must be able to represent the value or the decode +operation will fail. + +Structs, arrays and slices are also supported. Strings and arrays of bytes are +supported with a special, efficient representation (see below). When a slice is +decoded, if the existing slice has capacity the slice will be extended in place; +if not, a new array is allocated. Regardless, the length of the resuling slice +reports the number of elements decoded. + +Functions and channels cannot be sent in a gob. Attempting +to encode a value that contains one will fail. + +The rest of this comment documents the encoding, details that are not important +for most users. Details are presented bottom-up. + +An unsigned integer is sent one of two ways. If it is less than 128, it is sent +as a byte with that value. Otherwise it is sent as a minimal-length big-endian +(high byte first) byte stream holding the value, preceded by one byte holding the +byte count, negated. Thus 0 is transmitted as (00), 7 is transmitted as (07) and +256 is transmitted as (FE 01 00). + +A boolean is encoded within an unsigned integer: 0 for false, 1 for true. + +A signed integer, i, is encoded within an unsigned integer, u. Within u, bits 1 +upward contain the value; bit 0 says whether they should be complemented upon +receipt. The encode algorithm looks like this: + + uint u; + if i < 0 { + u = (^i << 1) | 1 // complement i, bit 0 is 1 + } else { + u = (i << 1) // do not complement i, bit 0 is 0 + } + encodeUnsigned(u) + +The low bit is therefore analogous to a sign bit, but making it the complement bit +instead guarantees that the largest negative integer is not a special case. For +example, -129=^128=(^256>>1) encodes as (FE 01 01). + +Floating-point numbers are always sent as a representation of a float64 value. +That value is converted to a uint64 using math.Float64bits. The uint64 is then +byte-reversed and sent as a regular unsigned integer. The byte-reversal means the +exponent and high-precision part of the mantissa go first. Since the low bits are +often zero, this can save encoding bytes. For instance, 17.0 is encoded in only +three bytes (FE 31 40). + +Strings and slices of bytes are sent as an unsigned count followed by that many +uninterpreted bytes of the value. + +All other slices and arrays are sent as an unsigned count followed by that many +elements using the standard gob encoding for their type, recursively. + +Maps are sent as an unsigned count followed by that man key, element +pairs. Empty but non-nil maps are sent, so if the sender has allocated +a map, the receiver will allocate a map even no elements are +transmitted. + +Structs are sent as a sequence of (field number, field value) pairs. The field +value is sent using the standard gob encoding for its type, recursively. If a +field has the zero value for its type, it is omitted from the transmission. The +field number is defined by the type of the encoded struct: the first field of the +encoded type is field 0, the second is field 1, etc. When encoding a value, the +field numbers are delta encoded for efficiency and the fields are always sent in +order of increasing field number; the deltas are therefore unsigned. The +initialization for the delta encoding sets the field number to -1, so an unsigned +integer field 0 with value 7 is transmitted as unsigned delta = 1, unsigned value += 7 or (01 07). Finally, after all the fields have been sent a terminating mark +denotes the end of the struct. That mark is a delta=0 value, which has +representation (00). + +Interface types are not checked for compatibility; all interface types are +treated, for transmission, as members of a single "interface" type, analogous to +int or []byte - in effect they're all treated as interface{}. Interface values +are transmitted as a string identifying the concrete type being sent (a name +that must be pre-defined by calling Register), followed by a byte count of the +length of the following data (so the value can be skipped if it cannot be +stored), followed by the usual encoding of concrete (dynamic) value stored in +the interface value. (A nil interface value is identified by the empty string +and transmits no value.) Upon receipt, the decoder verifies that the unpacked +concrete item satisfies the interface of the receiving variable. + +The representation of types is described below. When a type is defined on a given +connection between an Encoder and Decoder, it is assigned a signed integer type +id. When Encoder.Encode(v) is called, it makes sure there is an id assigned for +the type of v and all its elements and then it sends the pair (typeid, encoded-v) +where typeid is the type id of the encoded type of v and encoded-v is the gob +encoding of the value v. + +To define a type, the encoder chooses an unused, positive type id and sends the +pair (-type id, encoded-type) where encoded-type is the gob encoding of a wireType +description, constructed from these types: + + type wireType struct { + ArrayT *ArrayType + SliceT *SliceType + StructT *StructType + MapT *MapType + } + type ArrayType struct { + CommonType + Elem typeId + Len int + } + type CommonType struct { + Name string // the name of the struct type + Id int // the id of the type, repeated so it's inside the type + } + type SliceType struct { + CommonType + Elem typeId + } + type StructType struct { + CommonType + Field []*fieldType // the fields of the struct. + } + type FieldType struct { + Name string // the name of the field. + Id int // the type id of the field, which must be already defined + } + type MapType struct { + CommonType + Key typeId + Elem typeId + } + +If there are nested type ids, the types for all inner type ids must be defined +before the top-level type id is used to describe an encoded-v. + +For simplicity in setup, the connection is defined to understand these types a +priori, as well as the basic gob types int, uint, etc. Their ids are: + + bool 1 + int 2 + uint 3 + float 4 + []byte 5 + string 6 + complex 7 + interface 8 + // gap for reserved ids. + WireType 16 + ArrayType 17 + CommonType 18 + SliceType 19 + StructType 20 + FieldType 21 + // 22 is slice of fieldType. + MapType 23 + +Finally, each message created by a call to Encode is preceded by an encoded +unsigned integer count of the number of bytes remaining in the message. After +the initial type name, interface values are wrapped the same way; in effect, the +interface value acts like a recursive invocation of Encode. + +In summary, a gob stream looks like + + (byteCount (-type id, encoding of a wireType)* (type id, encoding of a value))* + +where * signifies zero or more repetitions and the type id of a value must +be predefined or be defined before the value in the stream. + +See "Gobs of data" for a design discussion of the gob wire format: +http://blog.golang.org/2011/03/gobs-of-data.html +*/ +package gob + +/* +Grammar: + +Tokens starting with a lower case letter are terminals; int(n) +and uint(n) represent the signed/unsigned encodings of the value n. + +GobStream: + DelimitedMessage* +DelimitedMessage: + uint(lengthOfMessage) Message +Message: + TypeSequence TypedValue +TypeSequence + (TypeDefinition DelimitedTypeDefinition*)? +DelimitedTypeDefinition: + uint(lengthOfTypeDefinition) TypeDefinition +TypedValue: + int(typeId) Value +TypeDefinition: + int(-typeId) encodingOfWireType +Value: + SingletonValue | StructValue +SingletonValue: + uint(0) FieldValue +FieldValue: + builtinValue | ArrayValue | MapValue | SliceValue | StructValue | InterfaceValue +InterfaceValue: + NilInterfaceValue | NonNilInterfaceValue +NilInterfaceValue: + uint(0) +NonNilInterfaceValue: + ConcreteTypeName TypeSequence InterfaceContents +ConcreteTypeName: + uint(lengthOfName) [already read=n] name +InterfaceContents: + int(concreteTypeId) DelimitedValue +DelimitedValue: + uint(length) Value +ArrayValue: + uint(n) FieldValue*n [n elements] +MapValue: + uint(n) (FieldValue FieldValue)*n [n (key, value) pairs] +SliceValue: + uint(n) FieldValue*n [n elements] +StructValue: + (uint(fieldDelta) FieldValue)* +*/ + +/* +For implementers and the curious, here is an encoded example. Given + type Point struct {X, Y int} +and the value + p := Point{22, 33} +the bytes transmitted that encode p will be: + 1f ff 81 03 01 01 05 50 6f 69 6e 74 01 ff 82 00 + 01 02 01 01 58 01 04 00 01 01 59 01 04 00 00 00 + 07 ff 82 01 2c 01 42 00 +They are determined as follows. + +Since this is the first transmission of type Point, the type descriptor +for Point itself must be sent before the value. This is the first type +we've sent on this Encoder, so it has type id 65 (0 through 64 are +reserved). + + 1f // This item (a type descriptor) is 31 bytes long. + ff 81 // The negative of the id for the type we're defining, -65. + // This is one byte (indicated by FF = -1) followed by + // ^-65<<1 | 1. The low 1 bit signals to complement the + // rest upon receipt. + + // Now we send a type descriptor, which is itself a struct (wireType). + // The type of wireType itself is known (it's built in, as is the type of + // all its components), so we just need to send a *value* of type wireType + // that represents type "Point". + // Here starts the encoding of that value. + // Set the field number implicitly to -1; this is done at the beginning + // of every struct, including nested structs. + 03 // Add 3 to field number; now 2 (wireType.structType; this is a struct). + // structType starts with an embedded commonType, which appears + // as a regular structure here too. + 01 // add 1 to field number (now 0); start of embedded commonType. + 01 // add 1 to field number (now 0, the name of the type) + 05 // string is (unsigned) 5 bytes long + 50 6f 69 6e 74 // wireType.structType.commonType.name = "Point" + 01 // add 1 to field number (now 1, the id of the type) + ff 82 // wireType.structType.commonType._id = 65 + 00 // end of embedded wiretype.structType.commonType struct + 01 // add 1 to field number (now 1, the field array in wireType.structType) + 02 // There are two fields in the type (len(structType.field)) + 01 // Start of first field structure; add 1 to get field number 0: field[0].name + 01 // 1 byte + 58 // structType.field[0].name = "X" + 01 // Add 1 to get field number 1: field[0].id + 04 // structType.field[0].typeId is 2 (signed int). + 00 // End of structType.field[0]; start structType.field[1]; set field number to -1. + 01 // Add 1 to get field number 0: field[1].name + 01 // 1 byte + 59 // structType.field[1].name = "Y" + 01 // Add 1 to get field number 1: field[0].id + 04 // struct.Type.field[1].typeId is 2 (signed int). + 00 // End of structType.field[1]; end of structType.field. + 00 // end of wireType.structType structure + 00 // end of wireType structure + +Now we can send the Point value. Again the field number resets to -1: + + 07 // this value is 7 bytes long + ff 82 // the type number, 65 (1 byte (-FF) followed by 65<<1) + 01 // add one to field number, yielding field 0 + 2c // encoding of signed "22" (0x22 = 44 = 22<<1); Point.x = 22 + 01 // add one to field number, yielding field 1 + 42 // encoding of signed "33" (0x42 = 66 = 33<<1); Point.y = 33 + 00 // end of structure + +The type encoding is long and fairly intricate but we send it only once. +If p is transmitted a second time, the type is already known so the +output will be just: + + 07 ff 82 01 2c 01 42 00 + +A single non-struct value at top level is transmitted like a field with +delta tag 0. For instance, a signed integer with value 3 presented as +the argument to Encode will emit: + + 03 04 00 06 + +Which represents: + + 03 // this value is 3 bytes long + 04 // the type number, 2, represents an integer + 00 // tag delta 0 + 06 // value 3 + +*/ diff --git a/libgo/go/encoding/gob/dump.go b/libgo/go/encoding/gob/dump.go new file mode 100644 index 0000000..0d0017c --- /dev/null +++ b/libgo/go/encoding/gob/dump.go @@ -0,0 +1,22 @@ +package main + +// Need to compile package gob with debug.go to build this program. + +import ( + "encoding/gob" + "fmt" + "os" +) + +func main() { + var err error + file := os.Stdin + if len(os.Args) > 1 { + file, err = os.Open(os.Args[1]) + if err != nil { + fmt.Fprintf(os.Stderr, "dump: %s\n", err) + os.Exit(1) + } + } + gob.Debug(file) +} diff --git a/libgo/go/encoding/gob/encode.go b/libgo/go/encoding/gob/encode.go new file mode 100644 index 0000000..c7e4823 --- /dev/null +++ b/libgo/go/encoding/gob/encode.go @@ -0,0 +1,717 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import ( + "bytes" + "math" + "reflect" + "unsafe" +) + +const uint64Size = int(unsafe.Sizeof(uint64(0))) + +// encoderState is the global execution state of an instance of the encoder. +// Field numbers are delta encoded and always increase. The field +// number is initialized to -1 so 0 comes out as delta(1). A delta of +// 0 terminates the structure. +type encoderState struct { + enc *Encoder + b *bytes.Buffer + sendZero bool // encoding an array element or map key/value pair; send zero values + fieldnum int // the last field number written. + buf [1 + uint64Size]byte // buffer used by the encoder; here to avoid allocation. + next *encoderState // for free list +} + +func (enc *Encoder) newEncoderState(b *bytes.Buffer) *encoderState { + e := enc.freeList + if e == nil { + e = new(encoderState) + e.enc = enc + } else { + enc.freeList = e.next + } + e.sendZero = false + e.fieldnum = 0 + e.b = b + return e +} + +func (enc *Encoder) freeEncoderState(e *encoderState) { + e.next = enc.freeList + enc.freeList = e +} + +// Unsigned integers have a two-state encoding. If the number is less +// than 128 (0 through 0x7F), its value is written directly. +// Otherwise the value is written in big-endian byte order preceded +// by the byte length, negated. + +// encodeUint writes an encoded unsigned integer to state.b. +func (state *encoderState) encodeUint(x uint64) { + if x <= 0x7F { + err := state.b.WriteByte(uint8(x)) + if err != nil { + error_(err) + } + return + } + i := uint64Size + for x > 0 { + state.buf[i] = uint8(x) + x >>= 8 + i-- + } + state.buf[i] = uint8(i - uint64Size) // = loop count, negated + _, err := state.b.Write(state.buf[i : uint64Size+1]) + if err != nil { + error_(err) + } +} + +// encodeInt writes an encoded signed integer to state.w. +// The low bit of the encoding says whether to bit complement the (other bits of the) +// uint to recover the int. +func (state *encoderState) encodeInt(i int64) { + var x uint64 + if i < 0 { + x = uint64(^i<<1) | 1 + } else { + x = uint64(i << 1) + } + state.encodeUint(uint64(x)) +} + +// encOp is the signature of an encoding operator for a given type. +type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer) + +// The 'instructions' of the encoding machine +type encInstr struct { + op encOp + field int // field number + indir int // how many pointer indirections to reach the value in the struct + offset uintptr // offset in the structure of the field to encode +} + +// update emits a field number and updates the state to record its value for delta encoding. +// If the instruction pointer is nil, it does nothing +func (state *encoderState) update(instr *encInstr) { + if instr != nil { + state.encodeUint(uint64(instr.field - state.fieldnum)) + state.fieldnum = instr.field + } +} + +// Each encoder for a composite is responsible for handling any +// indirections associated with the elements of the data structure. +// If any pointer so reached is nil, no bytes are written. If the +// data item is zero, no bytes are written. Single values - ints, +// strings etc. - are indirected before calling their encoders. +// Otherwise, the output (for a scalar) is the field number, as an +// encoded integer, followed by the field data in its appropriate +// format. + +// encIndirect dereferences p indir times and returns the result. +func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer { + for ; indir > 0; indir-- { + p = *(*unsafe.Pointer)(p) + if p == nil { + return unsafe.Pointer(nil) + } + } + return p +} + +// encBool encodes the bool with address p as an unsigned 0 or 1. +func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) { + b := *(*bool)(p) + if b || state.sendZero { + state.update(i) + if b { + state.encodeUint(1) + } else { + state.encodeUint(0) + } + } +} + +// encInt encodes the int with address p. +func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +// encUint encodes the uint with address p. +func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +// encInt8 encodes the int8 with address p. +func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int8)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +// encUint8 encodes the uint8 with address p. +func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint8)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +// encInt16 encodes the int16 with address p. +func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int16)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +// encUint16 encodes the uint16 with address p. +func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint16)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +// encInt32 encodes the int32 with address p. +func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int32)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +// encUint encodes the uint32 with address p. +func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint32)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +// encInt64 encodes the int64 with address p. +func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := *(*int64)(p) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +// encInt64 encodes the uint64 with address p. +func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := *(*uint64)(p) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +// encUintptr encodes the uintptr with address p. +func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uintptr)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +// floatBits returns a uint64 holding the bits of a floating-point number. +// Floating-point numbers are transmitted as uint64s holding the bits +// of the underlying representation. They are sent byte-reversed, with +// the exponent end coming out first, so integer floating point numbers +// (for example) transmit more compactly. This routine does the +// swizzling. +func floatBits(f float64) uint64 { + u := math.Float64bits(f) + var v uint64 + for i := 0; i < 8; i++ { + v <<= 8 + v |= u & 0xFF + u >>= 8 + } + return v +} + +// encFloat32 encodes the float32 with address p. +func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) { + f := *(*float32)(p) + if f != 0 || state.sendZero { + v := floatBits(float64(f)) + state.update(i) + state.encodeUint(v) + } +} + +// encFloat64 encodes the float64 with address p. +func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) { + f := *(*float64)(p) + if f != 0 || state.sendZero { + state.update(i) + v := floatBits(f) + state.encodeUint(v) + } +} + +// encComplex64 encodes the complex64 with address p. +// Complex numbers are just a pair of floating-point numbers, real part first. +func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) { + c := *(*complex64)(p) + if c != 0+0i || state.sendZero { + rpart := floatBits(float64(real(c))) + ipart := floatBits(float64(imag(c))) + state.update(i) + state.encodeUint(rpart) + state.encodeUint(ipart) + } +} + +// encComplex128 encodes the complex128 with address p. +func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) { + c := *(*complex128)(p) + if c != 0+0i || state.sendZero { + rpart := floatBits(real(c)) + ipart := floatBits(imag(c)) + state.update(i) + state.encodeUint(rpart) + state.encodeUint(ipart) + } +} + +// encUint8Array encodes the byte slice whose header has address p. +// Byte arrays are encoded as an unsigned count followed by the raw bytes. +func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) { + b := *(*[]byte)(p) + if len(b) > 0 || state.sendZero { + state.update(i) + state.encodeUint(uint64(len(b))) + state.b.Write(b) + } +} + +// encString encodes the string whose header has address p. +// Strings are encoded as an unsigned count followed by the raw bytes. +func encString(i *encInstr, state *encoderState, p unsafe.Pointer) { + s := *(*string)(p) + if len(s) > 0 || state.sendZero { + state.update(i) + state.encodeUint(uint64(len(s))) + state.b.WriteString(s) + } +} + +// encStructTerminator encodes the end of an encoded struct +// as delta field number of 0. +func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) { + state.encodeUint(0) +} + +// Execution engine + +// encEngine an array of instructions indexed by field number of the encoding +// data, typically a struct. It is executed top to bottom, walking the struct. +type encEngine struct { + instr []encInstr +} + +const singletonField = 0 + +// encodeSingle encodes a single top-level non-struct value. +func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintptr) { + state := enc.newEncoderState(b) + state.fieldnum = singletonField + // There is no surrounding struct to frame the transmission, so we must + // generate data even if the item is zero. To do this, set sendZero. + state.sendZero = true + instr := &engine.instr[singletonField] + p := unsafe.Pointer(basep) // offset will be zero + if instr.indir > 0 { + if p = encIndirect(p, instr.indir); p == nil { + return + } + } + instr.op(instr, state, p) + enc.freeEncoderState(state) +} + +// encodeStruct encodes a single struct value. +func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintptr) { + state := enc.newEncoderState(b) + state.fieldnum = -1 + for i := 0; i < len(engine.instr); i++ { + instr := &engine.instr[i] + p := unsafe.Pointer(basep + instr.offset) + if instr.indir > 0 { + if p = encIndirect(p, instr.indir); p == nil { + continue + } + } + instr.op(instr, state, p) + } + enc.freeEncoderState(state) +} + +// encodeArray encodes the array whose 0th element is at p. +func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) { + state := enc.newEncoderState(b) + state.fieldnum = -1 + state.sendZero = true + state.encodeUint(uint64(length)) + for i := 0; i < length; i++ { + elemp := p + up := unsafe.Pointer(elemp) + if elemIndir > 0 { + if up = encIndirect(up, elemIndir); up == nil { + errorf("encodeArray: nil element") + } + elemp = uintptr(up) + } + op(nil, state, unsafe.Pointer(elemp)) + p += uintptr(elemWid) + } + enc.freeEncoderState(state) +} + +// encodeReflectValue is a helper for maps. It encodes the value v. +func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir int) { + for i := 0; i < indir && v.IsValid(); i++ { + v = reflect.Indirect(v) + } + if !v.IsValid() { + errorf("encodeReflectValue: nil element") + } + op(nil, state, unsafe.Pointer(unsafeAddr(v))) +} + +// encodeMap encodes a map as unsigned count followed by key:value pairs. +// Because map internals are not exposed, we must use reflection rather than +// addresses. +func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp encOp, keyIndir, elemIndir int) { + state := enc.newEncoderState(b) + state.fieldnum = -1 + state.sendZero = true + keys := mv.MapKeys() + state.encodeUint(uint64(len(keys))) + for _, key := range keys { + encodeReflectValue(state, key, keyOp, keyIndir) + encodeReflectValue(state, mv.MapIndex(key), elemOp, elemIndir) + } + enc.freeEncoderState(state) +} + +// encodeInterface encodes the interface value iv. +// To send an interface, we send a string identifying the concrete type, followed +// by the type identifier (which might require defining that type right now), followed +// by the concrete value. A nil value gets sent as the empty string for the name, +// followed by no value. +func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) { + state := enc.newEncoderState(b) + state.fieldnum = -1 + state.sendZero = true + if iv.IsNil() { + state.encodeUint(0) + return + } + + ut := userType(iv.Elem().Type()) + name, ok := concreteTypeToName[ut.base] + if !ok { + errorf("type not registered for interface: %s", ut.base) + } + // Send the name. + state.encodeUint(uint64(len(name))) + _, err := state.b.WriteString(name) + if err != nil { + error_(err) + } + // Define the type id if necessary. + enc.sendTypeDescriptor(enc.writer(), state, ut) + // Send the type id. + enc.sendTypeId(state, ut) + // Encode the value into a new buffer. Any nested type definitions + // should be written to b, before the encoded value. + enc.pushWriter(b) + data := new(bytes.Buffer) + data.Write(spaceForLength) + enc.encode(data, iv.Elem(), ut) + if enc.err != nil { + error_(enc.err) + } + enc.popWriter() + enc.writeMessage(b, data) + if enc.err != nil { + error_(err) + } + enc.freeEncoderState(state) +} + +// isZero returns whether the value is the zero of its type. +func isZero(val reflect.Value) bool { + switch val.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return val.Len() == 0 + case reflect.Bool: + return !val.Bool() + case reflect.Complex64, reflect.Complex128: + return val.Complex() == 0 + case reflect.Chan, reflect.Func, reflect.Ptr: + return val.IsNil() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return val.Int() == 0 + case reflect.Float32, reflect.Float64: + return val.Float() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return val.Uint() == 0 + } + panic("unknown type in isZero " + val.Type().String()) +} + +// encGobEncoder encodes a value that implements the GobEncoder interface. +// The data is sent as a byte array. +func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, v reflect.Value) { + // TODO: should we catch panics from the called method? + // We know it's a GobEncoder, so just call the method directly. + data, err := v.Interface().(GobEncoder).GobEncode() + if err != nil { + error_(err) + } + state := enc.newEncoderState(b) + state.fieldnum = -1 + state.encodeUint(uint64(len(data))) + state.b.Write(data) + enc.freeEncoderState(state) +} + +var encOpTable = [...]encOp{ + reflect.Bool: encBool, + reflect.Int: encInt, + reflect.Int8: encInt8, + reflect.Int16: encInt16, + reflect.Int32: encInt32, + reflect.Int64: encInt64, + reflect.Uint: encUint, + reflect.Uint8: encUint8, + reflect.Uint16: encUint16, + reflect.Uint32: encUint32, + reflect.Uint64: encUint64, + reflect.Uintptr: encUintptr, + reflect.Float32: encFloat32, + reflect.Float64: encFloat64, + reflect.Complex64: encComplex64, + reflect.Complex128: encComplex128, + reflect.String: encString, +} + +// encOpFor returns (a pointer to) the encoding op for the base type under rt and +// the indirection count to reach it. +func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) { + ut := userType(rt) + // If the type implements GobEncoder, we handle it without further processing. + if ut.isGobEncoder { + return enc.gobEncodeOpFor(ut) + } + // If this type is already in progress, it's a recursive type (e.g. map[string]*T). + // Return the pointer to the op we're already building. + if opPtr := inProgress[rt]; opPtr != nil { + return opPtr, ut.indir + } + typ := ut.base + indir := ut.indir + k := typ.Kind() + var op encOp + if int(k) < len(encOpTable) { + op = encOpTable[k] + } + if op == nil { + inProgress[rt] = &op + // Special cases + switch t := typ; t.Kind() { + case reflect.Slice: + if t.Elem().Kind() == reflect.Uint8 { + op = encUint8Array + break + } + // Slices have a header; we decode it to find the underlying array. + elemOp, indir := enc.encOpFor(t.Elem(), inProgress) + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + slice := (*reflect.SliceHeader)(p) + if !state.sendZero && slice.Len == 0 { + return + } + state.update(i) + state.enc.encodeArray(state.b, slice.Data, *elemOp, t.Elem().Size(), indir, int(slice.Len)) + } + case reflect.Array: + // True arrays have size in the type. + elemOp, indir := enc.encOpFor(t.Elem(), inProgress) + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + state.update(i) + state.enc.encodeArray(state.b, uintptr(p), *elemOp, t.Elem().Size(), indir, t.Len()) + } + case reflect.Map: + keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress) + elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + // Maps cannot be accessed by moving addresses around the way + // that slices etc. can. We must recover a full reflection value for + // the iteration. + v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p))) + mv := reflect.Indirect(v) + // We send zero-length (but non-nil) maps because the + // receiver might want to use the map. (Maps don't use append.) + if !state.sendZero && mv.IsNil() { + return + } + state.update(i) + state.enc.encodeMap(state.b, mv, *keyOp, *elemOp, keyIndir, elemIndir) + } + case reflect.Struct: + // Generate a closure that calls out to the engine for the nested type. + enc.getEncEngine(userType(typ)) + info := mustGetTypeInfo(typ) + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + state.update(i) + // indirect through info to delay evaluation for recursive structs + state.enc.encodeStruct(state.b, info.encoder, uintptr(p)) + } + case reflect.Interface: + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + // Interfaces transmit the name and contents of the concrete + // value they contain. + v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p))) + iv := reflect.Indirect(v) + if !state.sendZero && (!iv.IsValid() || iv.IsNil()) { + return + } + state.update(i) + state.enc.encodeInterface(state.b, iv) + } + } + } + if op == nil { + errorf("can't happen: encode type %s", rt) + } + return &op, indir +} + +// gobEncodeOpFor returns the op for a type that is known to implement +// GobEncoder. +func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { + rt := ut.user + if ut.encIndir == -1 { + rt = reflect.PtrTo(rt) + } else if ut.encIndir > 0 { + for i := int8(0); i < ut.encIndir; i++ { + rt = rt.Elem() + } + } + var op encOp + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + var v reflect.Value + if ut.encIndir == -1 { + // Need to climb up one level to turn value into pointer. + v = reflect.ValueOf(unsafe.Unreflect(rt, unsafe.Pointer(&p))) + } else { + v = reflect.ValueOf(unsafe.Unreflect(rt, p)) + } + if !state.sendZero && isZero(v) { + return + } + state.update(i) + state.enc.encodeGobEncoder(state.b, v) + } + return &op, int(ut.encIndir) // encIndir: op will get called with p == address of receiver. +} + +// compileEnc returns the engine to compile the type. +func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { + srt := ut.base + engine := new(encEngine) + seen := make(map[reflect.Type]*encOp) + rt := ut.base + if ut.isGobEncoder { + rt = ut.user + } + if !ut.isGobEncoder && + srt.Kind() == reflect.Struct { + for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); fieldNum++ { + f := srt.Field(fieldNum) + if !isExported(f.Name) { + continue + } + op, indir := enc.encOpFor(f.Type, seen) + engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, indir, uintptr(f.Offset)}) + wireFieldNum++ + } + if srt.NumField() > 0 && len(engine.instr) == 0 { + errorf("type %s has no exported fields", rt) + } + engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, 0, 0}) + } else { + engine.instr = make([]encInstr, 1) + op, indir := enc.encOpFor(rt, seen) + engine.instr[0] = encInstr{*op, singletonField, indir, 0} // offset is zero + } + return engine +} + +// getEncEngine returns the engine to compile the type. +// typeLock must be held (or we're in initialization and guaranteed single-threaded). +func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine { + info, err1 := getTypeInfo(ut) + if err1 != nil { + error_(err1) + } + if info.encoder == nil { + // mark this engine as underway before compiling to handle recursive types. + info.encoder = new(encEngine) + info.encoder = enc.compileEnc(ut) + } + return info.encoder +} + +// lockAndGetEncEngine is a function that locks and compiles. +// This lets us hold the lock only while compiling, not when encoding. +func (enc *Encoder) lockAndGetEncEngine(ut *userTypeInfo) *encEngine { + typeLock.Lock() + defer typeLock.Unlock() + return enc.getEncEngine(ut) +} + +func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInfo) { + defer catchError(&enc.err) + engine := enc.lockAndGetEncEngine(ut) + indir := ut.indir + if ut.isGobEncoder { + indir = int(ut.encIndir) + } + for i := 0; i < indir; i++ { + value = reflect.Indirect(value) + } + if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct { + enc.encodeStruct(b, engine, unsafeAddr(value)) + } else { + enc.encodeSingle(b, engine, unsafeAddr(value)) + } +} diff --git a/libgo/go/encoding/gob/encoder.go b/libgo/go/encoding/gob/encoder.go new file mode 100644 index 0000000..e4a48df --- /dev/null +++ b/libgo/go/encoding/gob/encoder.go @@ -0,0 +1,251 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import ( + "bytes" + "errors" + "io" + "reflect" + "sync" +) + +// An Encoder manages the transmission of type and data information to the +// other side of a connection. +type Encoder struct { + mutex sync.Mutex // each item must be sent atomically + w []io.Writer // where to send the data + sent map[reflect.Type]typeId // which types we've already sent + countState *encoderState // stage for writing counts + freeList *encoderState // list of free encoderStates; avoids reallocation + byteBuf bytes.Buffer // buffer for top-level encoderState + err error +} + +// Before we encode a message, we reserve space at the head of the +// buffer in which to encode its length. This means we can use the +// buffer to assemble the message without another allocation. +const maxLength = 9 // Maximum size of an encoded length. +var spaceForLength = make([]byte, maxLength) + +// NewEncoder returns a new encoder that will transmit on the io.Writer. +func NewEncoder(w io.Writer) *Encoder { + enc := new(Encoder) + enc.w = []io.Writer{w} + enc.sent = make(map[reflect.Type]typeId) + enc.countState = enc.newEncoderState(new(bytes.Buffer)) + return enc +} + +// writer() returns the innermost writer the encoder is using +func (enc *Encoder) writer() io.Writer { + return enc.w[len(enc.w)-1] +} + +// pushWriter adds a writer to the encoder. +func (enc *Encoder) pushWriter(w io.Writer) { + enc.w = append(enc.w, w) +} + +// popWriter pops the innermost writer. +func (enc *Encoder) popWriter() { + enc.w = enc.w[0 : len(enc.w)-1] +} + +func (enc *Encoder) badType(rt reflect.Type) { + enc.setError(errors.New("gob: can't encode type " + rt.String())) +} + +func (enc *Encoder) setError(err error) { + if enc.err == nil { // remember the first. + enc.err = err + } +} + +// writeMessage sends the data item preceded by a unsigned count of its length. +func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) { + // Space has been reserved for the length at the head of the message. + // This is a little dirty: we grab the slice from the bytes.Buffer and massage + // it by hand. + message := b.Bytes() + messageLen := len(message) - maxLength + // Encode the length. + enc.countState.b.Reset() + enc.countState.encodeUint(uint64(messageLen)) + // Copy the length to be a prefix of the message. + offset := maxLength - enc.countState.b.Len() + copy(message[offset:], enc.countState.b.Bytes()) + // Write the data. + _, err := w.Write(message[offset:]) + // Drain the buffer and restore the space at the front for the count of the next message. + b.Reset() + b.Write(spaceForLength) + if err != nil { + enc.setError(err) + } +} + +// sendActualType sends the requested type, without further investigation, unless +// it's been sent before. +func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTypeInfo, actual reflect.Type) (sent bool) { + if _, alreadySent := enc.sent[actual]; alreadySent { + return false + } + typeLock.Lock() + info, err := getTypeInfo(ut) + typeLock.Unlock() + if err != nil { + enc.setError(err) + return + } + // Send the pair (-id, type) + // Id: + state.encodeInt(-int64(info.id)) + // Type: + enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo) + enc.writeMessage(w, state.b) + if enc.err != nil { + return + } + + // Remember we've sent this type, both what the user gave us and the base type. + enc.sent[ut.base] = info.id + if ut.user != ut.base { + enc.sent[ut.user] = info.id + } + // Now send the inner types + switch st := actual; st.Kind() { + case reflect.Struct: + for i := 0; i < st.NumField(); i++ { + enc.sendType(w, state, st.Field(i).Type) + } + case reflect.Array, reflect.Slice: + enc.sendType(w, state, st.Elem()) + case reflect.Map: + enc.sendType(w, state, st.Key()) + enc.sendType(w, state, st.Elem()) + } + return true +} + +// sendType sends the type info to the other side, if necessary. +func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) { + ut := userType(origt) + if ut.isGobEncoder { + // The rules are different: regardless of the underlying type's representation, + // we need to tell the other side that this exact type is a GobEncoder. + return enc.sendActualType(w, state, ut, ut.user) + } + + // It's a concrete value, so drill down to the base type. + switch rt := ut.base; rt.Kind() { + default: + // Basic types and interfaces do not need to be described. + return + case reflect.Slice: + // If it's []uint8, don't send; it's considered basic. + if rt.Elem().Kind() == reflect.Uint8 { + return + } + // Otherwise we do send. + break + case reflect.Array: + // arrays must be sent so we know their lengths and element types. + break + case reflect.Map: + // maps must be sent so we know their lengths and key/value types. + break + case reflect.Struct: + // structs must be sent so we know their fields. + break + case reflect.Chan, reflect.Func: + // Probably a bad field in a struct. + enc.badType(rt) + return + } + + return enc.sendActualType(w, state, ut, ut.base) +} + +// Encode transmits the data item represented by the empty interface value, +// guaranteeing that all necessary type information has been transmitted first. +func (enc *Encoder) Encode(e interface{}) error { + return enc.EncodeValue(reflect.ValueOf(e)) +} + +// sendTypeDescriptor makes sure the remote side knows about this type. +// It will send a descriptor if this is the first time the type has been +// sent. +func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *userTypeInfo) { + // Make sure the type is known to the other side. + // First, have we already sent this type? + rt := ut.base + if ut.isGobEncoder { + rt = ut.user + } + if _, alreadySent := enc.sent[rt]; !alreadySent { + // No, so send it. + sent := enc.sendType(w, state, rt) + if enc.err != nil { + return + } + // If the type info has still not been transmitted, it means we have + // a singleton basic type (int, []byte etc.) at top level. We don't + // need to send the type info but we do need to update enc.sent. + if !sent { + typeLock.Lock() + info, err := getTypeInfo(ut) + typeLock.Unlock() + if err != nil { + enc.setError(err) + return + } + enc.sent[rt] = info.id + } + } +} + +// sendTypeId sends the id, which must have already been defined. +func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) { + // Identify the type of this top-level value. + state.encodeInt(int64(enc.sent[ut.base])) +} + +// EncodeValue transmits the data item represented by the reflection value, +// guaranteeing that all necessary type information has been transmitted first. +func (enc *Encoder) EncodeValue(value reflect.Value) error { + // Make sure we're single-threaded through here, so multiple + // goroutines can share an encoder. + enc.mutex.Lock() + defer enc.mutex.Unlock() + + // Remove any nested writers remaining due to previous errors. + enc.w = enc.w[0:1] + + ut, err := validUserType(value.Type()) + if err != nil { + return err + } + + enc.err = nil + enc.byteBuf.Reset() + enc.byteBuf.Write(spaceForLength) + state := enc.newEncoderState(&enc.byteBuf) + + enc.sendTypeDescriptor(enc.writer(), state, ut) + enc.sendTypeId(state, ut) + if enc.err != nil { + return enc.err + } + + // Encode the object. + enc.encode(state.b, value, ut) + if enc.err == nil { + enc.writeMessage(enc.writer(), state.b) + } + + enc.freeEncoderState(state) + return enc.err +} diff --git a/libgo/go/encoding/gob/encoder_test.go b/libgo/go/encoding/gob/encoder_test.go new file mode 100644 index 0000000..bc5af12 --- /dev/null +++ b/libgo/go/encoding/gob/encoder_test.go @@ -0,0 +1,664 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import ( + "bytes" + "fmt" + "io" + "reflect" + "strings" + "testing" +) + +type ET2 struct { + X string +} + +type ET1 struct { + A int + Et2 *ET2 + Next *ET1 +} + +// Like ET1 but with a different name for a field +type ET3 struct { + A int + Et2 *ET2 + DifferentNext *ET1 +} + +// Like ET1 but with a different type for a field +type ET4 struct { + A int + Et2 float64 + Next int +} + +func TestEncoderDecoder(t *testing.T) { + b := new(bytes.Buffer) + enc := NewEncoder(b) + et1 := new(ET1) + et1.A = 7 + et1.Et2 = new(ET2) + err := enc.Encode(et1) + if err != nil { + t.Error("encoder fail:", err) + } + dec := NewDecoder(b) + newEt1 := new(ET1) + err = dec.Decode(newEt1) + if err != nil { + t.Fatal("error decoding ET1:", err) + } + + if !reflect.DeepEqual(et1, newEt1) { + t.Fatalf("invalid data for et1: expected %+v; got %+v", *et1, *newEt1) + } + if b.Len() != 0 { + t.Error("not at eof;", b.Len(), "bytes left") + } + + enc.Encode(et1) + newEt1 = new(ET1) + err = dec.Decode(newEt1) + if err != nil { + t.Fatal("round 2: error decoding ET1:", err) + } + if !reflect.DeepEqual(et1, newEt1) { + t.Fatalf("round 2: invalid data for et1: expected %+v; got %+v", *et1, *newEt1) + } + if b.Len() != 0 { + t.Error("round 2: not at eof;", b.Len(), "bytes left") + } + + // Now test with a running encoder/decoder pair that we recognize a type mismatch. + err = enc.Encode(et1) + if err != nil { + t.Error("round 3: encoder fail:", err) + } + newEt2 := new(ET2) + err = dec.Decode(newEt2) + if err == nil { + t.Fatal("round 3: expected `bad type' error decoding ET2") + } +} + +// Run one value through the encoder/decoder, but use the wrong type. +// Input is always an ET1; we compare it to whatever is under 'e'. +func badTypeCheck(e interface{}, shouldFail bool, msg string, t *testing.T) { + b := new(bytes.Buffer) + enc := NewEncoder(b) + et1 := new(ET1) + et1.A = 7 + et1.Et2 = new(ET2) + err := enc.Encode(et1) + if err != nil { + t.Error("encoder fail:", err) + } + dec := NewDecoder(b) + err = dec.Decode(e) + if shouldFail && err == nil { + t.Error("expected error for", msg) + } + if !shouldFail && err != nil { + t.Error("unexpected error for", msg, err) + } +} + +// Test that we recognize a bad type the first time. +func TestWrongTypeDecoder(t *testing.T) { + badTypeCheck(new(ET2), true, "no fields in common", t) + badTypeCheck(new(ET3), false, "different name of field", t) + badTypeCheck(new(ET4), true, "different type of field", t) +} + +func corruptDataCheck(s string, err error, t *testing.T) { + b := bytes.NewBufferString(s) + dec := NewDecoder(b) + err1 := dec.Decode(new(ET2)) + if err1 != err { + t.Errorf("from %q expected error %s; got %s", s, err, err1) + } +} + +// Check that we survive bad data. +func TestBadData(t *testing.T) { + corruptDataCheck("", io.EOF, t) + corruptDataCheck("\x7Fhi", io.ErrUnexpectedEOF, t) + corruptDataCheck("\x03now is the time for all good men", errBadType, t) +} + +// Types not supported by the Encoder. +var unsupportedValues = []interface{}{ + make(chan int), + func(a int) bool { return true }, +} + +func TestUnsupported(t *testing.T) { + var b bytes.Buffer + enc := NewEncoder(&b) + for _, v := range unsupportedValues { + err := enc.Encode(v) + if err == nil { + t.Errorf("expected error for %T; got none", v) + } + } +} + +func encAndDec(in, out interface{}) error { + b := new(bytes.Buffer) + enc := NewEncoder(b) + err := enc.Encode(in) + if err != nil { + return err + } + dec := NewDecoder(b) + err = dec.Decode(out) + if err != nil { + return err + } + return nil +} + +func TestTypeToPtrType(t *testing.T) { + // Encode a T, decode a *T + type Type0 struct { + A int + } + t0 := Type0{7} + t0p := new(Type0) + if err := encAndDec(t0, t0p); err != nil { + t.Error(err) + } +} + +func TestPtrTypeToType(t *testing.T) { + // Encode a *T, decode a T + type Type1 struct { + A uint + } + t1p := &Type1{17} + var t1 Type1 + if err := encAndDec(t1, t1p); err != nil { + t.Error(err) + } +} + +func TestTypeToPtrPtrPtrPtrType(t *testing.T) { + type Type2 struct { + A ****float64 + } + t2 := Type2{} + t2.A = new(***float64) + *t2.A = new(**float64) + **t2.A = new(*float64) + ***t2.A = new(float64) + ****t2.A = 27.4 + t2pppp := new(***Type2) + if err := encAndDec(t2, t2pppp); err != nil { + t.Fatal(err) + } + if ****(****t2pppp).A != ****t2.A { + t.Errorf("wrong value after decode: %g not %g", ****(****t2pppp).A, ****t2.A) + } +} + +func TestSlice(t *testing.T) { + type Type3 struct { + A []string + } + t3p := &Type3{[]string{"hello", "world"}} + var t3 Type3 + if err := encAndDec(t3, t3p); err != nil { + t.Error(err) + } +} + +func TestValueError(t *testing.T) { + // Encode a *T, decode a T + type Type4 struct { + A int + } + t4p := &Type4{3} + var t4 Type4 // note: not a pointer. + if err := encAndDec(t4p, t4); err == nil || strings.Index(err.Error(), "pointer") < 0 { + t.Error("expected error about pointer; got", err) + } +} + +func TestArray(t *testing.T) { + type Type5 struct { + A [3]string + B [3]byte + } + type Type6 struct { + A [2]string // can't hold t5.a + } + t5 := Type5{[3]string{"hello", ",", "world"}, [3]byte{1, 2, 3}} + var t5p Type5 + if err := encAndDec(t5, &t5p); err != nil { + t.Error(err) + } + var t6 Type6 + if err := encAndDec(t5, &t6); err == nil { + t.Error("should fail with mismatched array sizes") + } +} + +func TestRecursiveMapType(t *testing.T) { + type recursiveMap map[string]recursiveMap + r1 := recursiveMap{"A": recursiveMap{"B": nil, "C": nil}, "D": nil} + r2 := make(recursiveMap) + if err := encAndDec(r1, &r2); err != nil { + t.Error(err) + } +} + +func TestRecursiveSliceType(t *testing.T) { + type recursiveSlice []recursiveSlice + r1 := recursiveSlice{0: recursiveSlice{0: nil}, 1: nil} + r2 := make(recursiveSlice, 0) + if err := encAndDec(r1, &r2); err != nil { + t.Error(err) + } +} + +// Regression test for bug: must send zero values inside arrays +func TestDefaultsInArray(t *testing.T) { + type Type7 struct { + B []bool + I []int + S []string + F []float64 + } + t7 := Type7{ + []bool{false, false, true}, + []int{0, 0, 1}, + []string{"hi", "", "there"}, + []float64{0, 0, 1}, + } + var t7p Type7 + if err := encAndDec(t7, &t7p); err != nil { + t.Error(err) + } +} + +var testInt int +var testFloat32 float32 +var testString string +var testSlice []string +var testMap map[string]int +var testArray [7]int + +type SingleTest struct { + in interface{} + out interface{} + err string +} + +var singleTests = []SingleTest{ + {17, &testInt, ""}, + {float32(17.5), &testFloat32, ""}, + {"bike shed", &testString, ""}, + {[]string{"bike", "shed", "paint", "color"}, &testSlice, ""}, + {map[string]int{"seven": 7, "twelve": 12}, &testMap, ""}, + {[7]int{4, 55, 0, 0, 0, 0, 0}, &testArray, ""}, // case that once triggered a bug + {[7]int{4, 55, 1, 44, 22, 66, 1234}, &testArray, ""}, + + // Decode errors + {172, &testFloat32, "wrong type"}, +} + +func TestSingletons(t *testing.T) { + b := new(bytes.Buffer) + enc := NewEncoder(b) + dec := NewDecoder(b) + for _, test := range singleTests { + b.Reset() + err := enc.Encode(test.in) + if err != nil { + t.Errorf("error encoding %v: %s", test.in, err) + continue + } + err = dec.Decode(test.out) + switch { + case err != nil && test.err == "": + t.Errorf("error decoding %v: %s", test.in, err) + continue + case err == nil && test.err != "": + t.Errorf("expected error decoding %v: %s", test.in, test.err) + continue + case err != nil && test.err != "": + if strings.Index(err.Error(), test.err) < 0 { + t.Errorf("wrong error decoding %v: wanted %s, got %v", test.in, test.err, err) + } + continue + } + // Get rid of the pointer in the rhs + val := reflect.ValueOf(test.out).Elem().Interface() + if !reflect.DeepEqual(test.in, val) { + t.Errorf("decoding singleton: expected %v got %v", test.in, val) + } + } +} + +func TestStructNonStruct(t *testing.T) { + type Struct struct { + A string + } + type NonStruct string + s := Struct{"hello"} + var sp Struct + if err := encAndDec(s, &sp); err != nil { + t.Error(err) + } + var ns NonStruct + if err := encAndDec(s, &ns); err == nil { + t.Error("should get error for struct/non-struct") + } else if strings.Index(err.Error(), "type") < 0 { + t.Error("for struct/non-struct expected type error; got", err) + } + // Now try the other way + var nsp NonStruct + if err := encAndDec(ns, &nsp); err != nil { + t.Error(err) + } + if err := encAndDec(ns, &s); err == nil { + t.Error("should get error for non-struct/struct") + } else if strings.Index(err.Error(), "type") < 0 { + t.Error("for non-struct/struct expected type error; got", err) + } +} + +type interfaceIndirectTestI interface { + F() bool +} + +type interfaceIndirectTestT struct{} + +func (this *interfaceIndirectTestT) F() bool { + return true +} + +// A version of a bug reported on golang-nuts. Also tests top-level +// slice of interfaces. The issue was registering *T caused T to be +// stored as the concrete type. +func TestInterfaceIndirect(t *testing.T) { + Register(&interfaceIndirectTestT{}) + b := new(bytes.Buffer) + w := []interfaceIndirectTestI{&interfaceIndirectTestT{}} + err := NewEncoder(b).Encode(w) + if err != nil { + t.Fatal("encode error:", err) + } + + var r []interfaceIndirectTestI + err = NewDecoder(b).Decode(&r) + if err != nil { + t.Fatal("decode error:", err) + } +} + +// Now follow various tests that decode into things that can't represent the +// encoded value, all of which should be legal. + +// Also, when the ignored object contains an interface value, it may define +// types. Make sure that skipping the value still defines the types by using +// the encoder/decoder pair to send a value afterwards. If an interface +// is sent, its type in the test is always NewType0, so this checks that the +// encoder and decoder don't skew with respect to type definitions. + +type Struct0 struct { + I interface{} +} + +type NewType0 struct { + S string +} + +type ignoreTest struct { + in, out interface{} +} + +var ignoreTests = []ignoreTest{ + // Decode normal struct into an empty struct + {&struct{ A int }{23}, &struct{}{}}, + // Decode normal struct into a nil. + {&struct{ A int }{23}, nil}, + // Decode singleton string into a nil. + {"hello, world", nil}, + // Decode singleton slice into a nil. + {[]int{1, 2, 3, 4}, nil}, + // Decode struct containing an interface into a nil. + {&Struct0{&NewType0{"value0"}}, nil}, + // Decode singleton slice of interfaces into a nil. + {[]interface{}{"hi", &NewType0{"value1"}, 23}, nil}, +} + +func TestDecodeIntoNothing(t *testing.T) { + Register(new(NewType0)) + for i, test := range ignoreTests { + b := new(bytes.Buffer) + enc := NewEncoder(b) + err := enc.Encode(test.in) + if err != nil { + t.Errorf("%d: encode error %s:", i, err) + continue + } + dec := NewDecoder(b) + err = dec.Decode(test.out) + if err != nil { + t.Errorf("%d: decode error: %s", i, err) + continue + } + // Now see if the encoder and decoder are in a consistent state. + str := fmt.Sprintf("Value %d", i) + err = enc.Encode(&NewType0{str}) + if err != nil { + t.Fatalf("%d: NewType0 encode error: %s", i, err) + } + ns := new(NewType0) + err = dec.Decode(ns) + if err != nil { + t.Fatalf("%d: NewType0 decode error: %s", i, err) + } + if ns.S != str { + t.Fatalf("%d: expected %q got %q", i, str, ns.S) + } + } +} + +// Another bug from golang-nuts, involving nested interfaces. +type Bug0Outer struct { + Bug0Field interface{} +} + +type Bug0Inner struct { + A int +} + +func TestNestedInterfaces(t *testing.T) { + var buf bytes.Buffer + e := NewEncoder(&buf) + d := NewDecoder(&buf) + Register(new(Bug0Outer)) + Register(new(Bug0Inner)) + f := &Bug0Outer{&Bug0Outer{&Bug0Inner{7}}} + var v interface{} = f + err := e.Encode(&v) + if err != nil { + t.Fatal("Encode:", err) + } + err = d.Decode(&v) + if err != nil { + t.Fatal("Decode:", err) + } + // Make sure it decoded correctly. + outer1, ok := v.(*Bug0Outer) + if !ok { + t.Fatalf("v not Bug0Outer: %T", v) + } + outer2, ok := outer1.Bug0Field.(*Bug0Outer) + if !ok { + t.Fatalf("v.Bug0Field not Bug0Outer: %T", outer1.Bug0Field) + } + inner, ok := outer2.Bug0Field.(*Bug0Inner) + if !ok { + t.Fatalf("v.Bug0Field.Bug0Field not Bug0Inner: %T", outer2.Bug0Field) + } + if inner.A != 7 { + t.Fatalf("final value %d; expected %d", inner.A, 7) + } +} + +// The bugs keep coming. We forgot to send map subtypes before the map. + +type Bug1Elem struct { + Name string + Id int +} + +type Bug1StructMap map[string]Bug1Elem + +func bug1EncDec(in Bug1StructMap, out *Bug1StructMap) error { + return nil +} + +func TestMapBug1(t *testing.T) { + in := make(Bug1StructMap) + in["val1"] = Bug1Elem{"elem1", 1} + in["val2"] = Bug1Elem{"elem2", 2} + + b := new(bytes.Buffer) + enc := NewEncoder(b) + err := enc.Encode(in) + if err != nil { + t.Fatal("encode:", err) + } + dec := NewDecoder(b) + out := make(Bug1StructMap) + err = dec.Decode(&out) + if err != nil { + t.Fatal("decode:", err) + } + if !reflect.DeepEqual(in, out) { + t.Errorf("mismatch: %v %v", in, out) + } +} + +func TestGobMapInterfaceEncode(t *testing.T) { + m := map[string]interface{}{ + "up": uintptr(0), + "i0": []int{-1}, + "i1": []int8{-1}, + "i2": []int16{-1}, + "i3": []int32{-1}, + "i4": []int64{-1}, + "u0": []uint{1}, + "u1": []uint8{1}, + "u2": []uint16{1}, + "u3": []uint32{1}, + "u4": []uint64{1}, + "f0": []float32{1}, + "f1": []float64{1}, + "c0": []complex64{complex(2, -2)}, + "c1": []complex128{complex(2, float64(-2))}, + "us": []uintptr{0}, + "bo": []bool{false}, + "st": []string{"s"}, + } + buf := bytes.NewBuffer(nil) + enc := NewEncoder(buf) + err := enc.Encode(m) + if err != nil { + t.Errorf("encode map: %s", err) + } +} + +func TestSliceReusesMemory(t *testing.T) { + buf := bytes.NewBuffer(nil) + // Bytes + { + x := []byte("abcd") + enc := NewEncoder(buf) + err := enc.Encode(x) + if err != nil { + t.Errorf("bytes: encode: %s", err) + } + // Decode into y, which is big enough. + y := []byte("ABCDE") + addr := &y[0] + dec := NewDecoder(buf) + err = dec.Decode(&y) + if err != nil { + t.Fatal("bytes: decode:", err) + } + if !bytes.Equal(x, y) { + t.Errorf("bytes: expected %q got %q\n", x, y) + } + if addr != &y[0] { + t.Errorf("bytes: unnecessary reallocation") + } + } + // general slice + { + x := []rune("abcd") + enc := NewEncoder(buf) + err := enc.Encode(x) + if err != nil { + t.Errorf("ints: encode: %s", err) + } + // Decode into y, which is big enough. + y := []rune("ABCDE") + addr := &y[0] + dec := NewDecoder(buf) + err = dec.Decode(&y) + if err != nil { + t.Fatal("ints: decode:", err) + } + if !reflect.DeepEqual(x, y) { + t.Errorf("ints: expected %q got %q\n", x, y) + } + if addr != &y[0] { + t.Errorf("ints: unnecessary reallocation") + } + } +} + +// Used to crash: negative count in recvMessage. +func TestBadCount(t *testing.T) { + b := []byte{0xfb, 0xa5, 0x82, 0x2f, 0xca, 0x1} + if err := NewDecoder(bytes.NewBuffer(b)).Decode(nil); err == nil { + t.Error("expected error from bad count") + } else if err.Error() != errBadCount.Error() { + t.Error("expected bad count error; got", err) + } +} + +// Verify that sequential Decoders built on a single input will +// succeed if the input implements ReadByte and there is no +// type information in the stream. +func TestSequentialDecoder(t *testing.T) { + b := new(bytes.Buffer) + enc := NewEncoder(b) + const count = 10 + for i := 0; i < count; i++ { + s := fmt.Sprintf("%d", i) + if err := enc.Encode(s); err != nil { + t.Error("encoder fail:", err) + } + } + for i := 0; i < count; i++ { + dec := NewDecoder(b) + var s string + if err := dec.Decode(&s); err != nil { + t.Fatal("decoder fail:", err) + } + if s != fmt.Sprintf("%d", i) { + t.Fatalf("decode expected %d got %s", i, s) + } + } +} diff --git a/libgo/go/encoding/gob/error.go b/libgo/go/encoding/gob/error.go new file mode 100644 index 0000000..fbae8b6 --- /dev/null +++ b/libgo/go/encoding/gob/error.go @@ -0,0 +1,39 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import "fmt" + +// Errors in decoding and encoding are handled using panic and recover. +// Panics caused by user error (that is, everything except run-time panics +// such as "index out of bounds" errors) do not leave the file that caused +// them, but are instead turned into plain error returns. Encoding and +// decoding functions and methods that do not return an error either use +// panic to report an error or are guaranteed error-free. + +// A gobError is used to distinguish errors (panics) generated in this package. +type gobError struct { + err error +} + +// errorf is like error_ but takes Printf-style arguments to construct an error. +// It always prefixes the message with "gob: ". +func errorf(format string, args ...interface{}) { + error_(fmt.Errorf("gob: "+format, args...)) +} + +// error wraps the argument error and uses it as the argument to panic. +func error_(err error) { + panic(gobError{err}) +} + +// catchError is meant to be used as a deferred function to turn a panic(gobError) into a +// plain error. It overwrites the error return of the function that deferred its call. +func catchError(err *error) { + if e := recover(); e != nil { + *err = e.(gobError).err // Will re-panic if not one of our errors, such as a runtime error. + } + return +} diff --git a/libgo/go/encoding/gob/gobencdec_test.go b/libgo/go/encoding/gob/gobencdec_test.go new file mode 100644 index 0000000..eacfd84 --- /dev/null +++ b/libgo/go/encoding/gob/gobencdec_test.go @@ -0,0 +1,528 @@ +// Copyright 20011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains tests of the GobEncoder/GobDecoder support. + +package gob + +import ( + "bytes" + "errors" + "fmt" + "io" + "strings" + "testing" +) + +// Types that implement the GobEncoder/Decoder interfaces. + +type ByteStruct struct { + a byte // not an exported field +} + +type StringStruct struct { + s string // not an exported field +} + +type ArrayStruct struct { + a [8192]byte // not an exported field +} + +type Gobber int + +type ValueGobber string // encodes with a value, decodes with a pointer. + +// The relevant methods + +func (g *ByteStruct) GobEncode() ([]byte, error) { + b := make([]byte, 3) + b[0] = g.a + b[1] = g.a + 1 + b[2] = g.a + 2 + return b, nil +} + +func (g *ByteStruct) GobDecode(data []byte) error { + if g == nil { + return errors.New("NIL RECEIVER") + } + // Expect N sequential-valued bytes. + if len(data) == 0 { + return io.EOF + } + g.a = data[0] + for i, c := range data { + if c != g.a+byte(i) { + return errors.New("invalid data sequence") + } + } + return nil +} + +func (g *StringStruct) GobEncode() ([]byte, error) { + return []byte(g.s), nil +} + +func (g *StringStruct) GobDecode(data []byte) error { + // Expect N sequential-valued bytes. + if len(data) == 0 { + return io.EOF + } + a := data[0] + for i, c := range data { + if c != a+byte(i) { + return errors.New("invalid data sequence") + } + } + g.s = string(data) + return nil +} + +func (a *ArrayStruct) GobEncode() ([]byte, error) { + return a.a[:], nil +} + +func (a *ArrayStruct) GobDecode(data []byte) error { + if len(data) != len(a.a) { + return errors.New("wrong length in array decode") + } + copy(a.a[:], data) + return nil +} + +func (g *Gobber) GobEncode() ([]byte, error) { + return []byte(fmt.Sprintf("VALUE=%d", *g)), nil +} + +func (g *Gobber) GobDecode(data []byte) error { + _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g)) + return err +} + +func (v ValueGobber) GobEncode() ([]byte, error) { + return []byte(fmt.Sprintf("VALUE=%s", v)), nil +} + +func (v *ValueGobber) GobDecode(data []byte) error { + _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v)) + return err +} + +// Structs that include GobEncodable fields. + +type GobTest0 struct { + X int // guarantee we have something in common with GobTest* + G *ByteStruct +} + +type GobTest1 struct { + X int // guarantee we have something in common with GobTest* + G *StringStruct +} + +type GobTest2 struct { + X int // guarantee we have something in common with GobTest* + G string // not a GobEncoder - should give us errors +} + +type GobTest3 struct { + X int // guarantee we have something in common with GobTest* + G *Gobber +} + +type GobTest4 struct { + X int // guarantee we have something in common with GobTest* + V ValueGobber +} + +type GobTest5 struct { + X int // guarantee we have something in common with GobTest* + V *ValueGobber +} + +type GobTestIgnoreEncoder struct { + X int // guarantee we have something in common with GobTest* +} + +type GobTestValueEncDec struct { + X int // guarantee we have something in common with GobTest* + G StringStruct // not a pointer. +} + +type GobTestIndirectEncDec struct { + X int // guarantee we have something in common with GobTest* + G ***StringStruct // indirections to the receiver. +} + +type GobTestArrayEncDec struct { + X int // guarantee we have something in common with GobTest* + A ArrayStruct // not a pointer. +} + +type GobTestIndirectArrayEncDec struct { + X int // guarantee we have something in common with GobTest* + A ***ArrayStruct // indirections to a large receiver. +} + +func TestGobEncoderField(t *testing.T) { + b := new(bytes.Buffer) + // First a field that's a structure. + enc := NewEncoder(b) + err := enc.Encode(GobTest0{17, &ByteStruct{'A'}}) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(GobTest0) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + if x.G.a != 'A' { + t.Errorf("expected 'A' got %c", x.G.a) + } + // Now a field that's not a structure. + b.Reset() + gobber := Gobber(23) + err = enc.Encode(GobTest3{17, &gobber}) + if err != nil { + t.Fatal("encode error:", err) + } + y := new(GobTest3) + err = dec.Decode(y) + if err != nil { + t.Fatal("decode error:", err) + } + if *y.G != 23 { + t.Errorf("expected '23 got %d", *y.G) + } +} + +// Even though the field is a value, we can still take its address +// and should be able to call the methods. +func TestGobEncoderValueField(t *testing.T) { + b := new(bytes.Buffer) + // First a field that's a structure. + enc := NewEncoder(b) + err := enc.Encode(GobTestValueEncDec{17, StringStruct{"HIJKL"}}) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(GobTestValueEncDec) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + if x.G.s != "HIJKL" { + t.Errorf("expected `HIJKL` got %s", x.G.s) + } +} + +// GobEncode/Decode should work even if the value is +// more indirect than the receiver. +func TestGobEncoderIndirectField(t *testing.T) { + b := new(bytes.Buffer) + // First a field that's a structure. + enc := NewEncoder(b) + s := &StringStruct{"HIJKL"} + sp := &s + err := enc.Encode(GobTestIndirectEncDec{17, &sp}) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(GobTestIndirectEncDec) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + if (***x.G).s != "HIJKL" { + t.Errorf("expected `HIJKL` got %s", (***x.G).s) + } +} + +// Test with a large field with methods. +func TestGobEncoderArrayField(t *testing.T) { + b := new(bytes.Buffer) + enc := NewEncoder(b) + var a GobTestArrayEncDec + a.X = 17 + for i := range a.A.a { + a.A.a[i] = byte(i) + } + err := enc.Encode(a) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(GobTestArrayEncDec) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + for i, v := range x.A.a { + if v != byte(i) { + t.Errorf("expected %x got %x", byte(i), v) + break + } + } +} + +// Test an indirection to a large field with methods. +func TestGobEncoderIndirectArrayField(t *testing.T) { + b := new(bytes.Buffer) + enc := NewEncoder(b) + var a GobTestIndirectArrayEncDec + a.X = 17 + var array ArrayStruct + ap := &array + app := &ap + a.A = &app + for i := range array.a { + array.a[i] = byte(i) + } + err := enc.Encode(a) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(GobTestIndirectArrayEncDec) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + for i, v := range (***x.A).a { + if v != byte(i) { + t.Errorf("expected %x got %x", byte(i), v) + break + } + } +} + +// As long as the fields have the same name and implement the +// interface, we can cross-connect them. Not sure it's useful +// and may even be bad but it works and it's hard to prevent +// without exposing the contents of the object, which would +// defeat the purpose. +func TestGobEncoderFieldsOfDifferentType(t *testing.T) { + // first, string in field to byte in field + b := new(bytes.Buffer) + enc := NewEncoder(b) + err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}}) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(GobTest0) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + if x.G.a != 'A' { + t.Errorf("expected 'A' got %c", x.G.a) + } + // now the other direction, byte in field to string in field + b.Reset() + err = enc.Encode(GobTest0{17, &ByteStruct{'X'}}) + if err != nil { + t.Fatal("encode error:", err) + } + y := new(GobTest1) + err = dec.Decode(y) + if err != nil { + t.Fatal("decode error:", err) + } + if y.G.s != "XYZ" { + t.Fatalf("expected `XYZ` got %c", y.G.s) + } +} + +// Test that we can encode a value and decode into a pointer. +func TestGobEncoderValueEncoder(t *testing.T) { + // first, string in field to byte in field + b := new(bytes.Buffer) + enc := NewEncoder(b) + err := enc.Encode(GobTest4{17, ValueGobber("hello")}) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(GobTest5) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + if *x.V != "hello" { + t.Errorf("expected `hello` got %s", x.V) + } +} + +func TestGobEncoderFieldTypeError(t *testing.T) { + // GobEncoder to non-decoder: error + b := new(bytes.Buffer) + enc := NewEncoder(b) + err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}}) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := &GobTest2{} + err = dec.Decode(x) + if err == nil { + t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)") + } + if strings.Index(err.Error(), "type") < 0 { + t.Fatal("expected type error; got", err) + } + // Non-encoder to GobDecoder: error + b.Reset() + err = enc.Encode(GobTest2{17, "ABC"}) + if err != nil { + t.Fatal("encode error:", err) + } + y := &GobTest1{} + err = dec.Decode(y) + if err == nil { + t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)") + } + if strings.Index(err.Error(), "type") < 0 { + t.Fatal("expected type error; got", err) + } +} + +// Even though ByteStruct is a struct, it's treated as a singleton at the top level. +func TestGobEncoderStructSingleton(t *testing.T) { + b := new(bytes.Buffer) + enc := NewEncoder(b) + err := enc.Encode(&ByteStruct{'A'}) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(ByteStruct) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + if x.a != 'A' { + t.Errorf("expected 'A' got %c", x.a) + } +} + +func TestGobEncoderNonStructSingleton(t *testing.T) { + b := new(bytes.Buffer) + enc := NewEncoder(b) + err := enc.Encode(Gobber(1234)) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + var x Gobber + err = dec.Decode(&x) + if err != nil { + t.Fatal("decode error:", err) + } + if x != 1234 { + t.Errorf("expected 1234 got %d", x) + } +} + +func TestGobEncoderIgnoreStructField(t *testing.T) { + b := new(bytes.Buffer) + // First a field that's a structure. + enc := NewEncoder(b) + err := enc.Encode(GobTest0{17, &ByteStruct{'A'}}) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(GobTestIgnoreEncoder) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + if x.X != 17 { + t.Errorf("expected 17 got %c", x.X) + } +} + +func TestGobEncoderIgnoreNonStructField(t *testing.T) { + b := new(bytes.Buffer) + // First a field that's a structure. + enc := NewEncoder(b) + gobber := Gobber(23) + err := enc.Encode(GobTest3{17, &gobber}) + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(GobTestIgnoreEncoder) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + if x.X != 17 { + t.Errorf("expected 17 got %c", x.X) + } +} + +func TestGobEncoderIgnoreNilEncoder(t *testing.T) { + b := new(bytes.Buffer) + // First a field that's a structure. + enc := NewEncoder(b) + err := enc.Encode(GobTest0{X: 18}) // G is nil + if err != nil { + t.Fatal("encode error:", err) + } + dec := NewDecoder(b) + x := new(GobTest0) + err = dec.Decode(x) + if err != nil { + t.Fatal("decode error:", err) + } + if x.X != 18 { + t.Errorf("expected x.X = 18, got %v", x.X) + } + if x.G != nil { + t.Errorf("expected x.G = nil, got %v", x.G) + } +} + +type gobDecoderBug0 struct { + foo, bar string +} + +func (br *gobDecoderBug0) String() string { + return br.foo + "-" + br.bar +} + +func (br *gobDecoderBug0) GobEncode() ([]byte, error) { + return []byte(br.String()), nil +} + +func (br *gobDecoderBug0) GobDecode(b []byte) error { + br.foo = "foo" + br.bar = "bar" + return nil +} + +// This was a bug: the receiver has a different indirection level +// than the variable. +func TestGobEncoderExtraIndirect(t *testing.T) { + gdb := &gobDecoderBug0{"foo", "bar"} + buf := new(bytes.Buffer) + e := NewEncoder(buf) + if err := e.Encode(gdb); err != nil { + t.Fatalf("encode: %v", err) + } + d := NewDecoder(buf) + var got *gobDecoderBug0 + if err := d.Decode(&got); err != nil { + t.Fatalf("decode: %v", err) + } + if got.foo != gdb.foo || got.bar != gdb.bar { + t.Errorf("got = %q, want %q", got, gdb) + } +} diff --git a/libgo/go/encoding/gob/timing_test.go b/libgo/go/encoding/gob/timing_test.go new file mode 100644 index 0000000..47437a6 --- /dev/null +++ b/libgo/go/encoding/gob/timing_test.go @@ -0,0 +1,94 @@ +// 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 gob + +import ( + "bytes" + "fmt" + "io" + "os" + "runtime" + "testing" +) + +type Bench struct { + A int + B float64 + C string + D []byte +} + +func benchmarkEndToEnd(r io.Reader, w io.Writer, b *testing.B) { + b.StopTimer() + enc := NewEncoder(w) + dec := NewDecoder(r) + bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} + b.StartTimer() + for i := 0; i < b.N; i++ { + if enc.Encode(bench) != nil { + panic("encode error") + } + if dec.Decode(bench) != nil { + panic("decode error") + } + } +} + +func BenchmarkEndToEndPipe(b *testing.B) { + r, w, err := os.Pipe() + if err != nil { + panic("can't get pipe:" + err.Error()) + } + benchmarkEndToEnd(r, w, b) +} + +func BenchmarkEndToEndByteBuffer(b *testing.B) { + var buf bytes.Buffer + benchmarkEndToEnd(&buf, &buf, b) +} + +func TestCountEncodeMallocs(t *testing.T) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} + runtime.UpdateMemStats() + mallocs := 0 - runtime.MemStats.Mallocs + const count = 1000 + for i := 0; i < count; i++ { + err := enc.Encode(bench) + if err != nil { + t.Fatal("encode:", err) + } + } + runtime.UpdateMemStats() + mallocs += runtime.MemStats.Mallocs + fmt.Printf("mallocs per encode of type Bench: %d\n", mallocs/count) +} + +func TestCountDecodeMallocs(t *testing.T) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} + const count = 1000 + for i := 0; i < count; i++ { + err := enc.Encode(bench) + if err != nil { + t.Fatal("encode:", err) + } + } + dec := NewDecoder(&buf) + runtime.UpdateMemStats() + mallocs := 0 - runtime.MemStats.Mallocs + for i := 0; i < count; i++ { + *bench = Bench{} + err := dec.Decode(&bench) + if err != nil { + t.Fatal("decode:", err) + } + } + runtime.UpdateMemStats() + mallocs += runtime.MemStats.Mallocs + fmt.Printf("mallocs per decode of type Bench: %d\n", mallocs/count) +} diff --git a/libgo/go/encoding/gob/type.go b/libgo/go/encoding/gob/type.go new file mode 100644 index 0000000..1b20843 --- /dev/null +++ b/libgo/go/encoding/gob/type.go @@ -0,0 +1,788 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import ( + "errors" + "fmt" + "os" + "reflect" + "sync" + "unicode" + "unicode/utf8" +) + +// userTypeInfo stores the information associated with a type the user has handed +// to the package. It's computed once and stored in a map keyed by reflection +// type. +type userTypeInfo struct { + user reflect.Type // the type the user handed us + base reflect.Type // the base type after all indirections + indir int // number of indirections to reach the base type + isGobEncoder bool // does the type implement GobEncoder? + isGobDecoder bool // does the type implement GobDecoder? + encIndir int8 // number of indirections to reach the receiver type; may be negative + decIndir int8 // number of indirections to reach the receiver type; may be negative +} + +var ( + // Protected by an RWMutex because we read it a lot and write + // it only when we see a new type, typically when compiling. + userTypeLock sync.RWMutex + userTypeCache = make(map[reflect.Type]*userTypeInfo) +) + +// validType returns, and saves, the information associated with user-provided type rt. +// If the user type is not valid, err will be non-nil. To be used when the error handler +// is not set up. +func validUserType(rt reflect.Type) (ut *userTypeInfo, err error) { + userTypeLock.RLock() + ut = userTypeCache[rt] + userTypeLock.RUnlock() + if ut != nil { + return + } + // Now set the value under the write lock. + userTypeLock.Lock() + defer userTypeLock.Unlock() + if ut = userTypeCache[rt]; ut != nil { + // Lost the race; not a problem. + return + } + ut = new(userTypeInfo) + ut.base = rt + ut.user = rt + // A type that is just a cycle of pointers (such as type T *T) cannot + // be represented in gobs, which need some concrete data. We use a + // cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6, + // pp 539-540. As we step through indirections, run another type at + // half speed. If they meet up, there's a cycle. + slowpoke := ut.base // walks half as fast as ut.base + for { + pt := ut.base + if pt.Kind() != reflect.Ptr { + break + } + ut.base = pt.Elem() + if ut.base == slowpoke { // ut.base lapped slowpoke + // recursive pointer type. + return nil, errors.New("can't represent recursive pointer type " + ut.base.String()) + } + if ut.indir%2 == 0 { + slowpoke = slowpoke.Elem() + } + ut.indir++ + } + ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderInterfaceType) + ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderInterfaceType) + userTypeCache[rt] = ut + return +} + +var ( + gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem() + gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem() +) + +// implementsInterface reports whether the type implements the +// gobEncoder/gobDecoder interface. +// It also returns the number of indirections required to get to the +// implementation. +func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) { + if typ == nil { + return + } + rt := typ + // The type might be a pointer and we need to keep + // dereferencing to the base type until we find an implementation. + for { + if rt.Implements(gobEncDecType) { + return true, indir + } + if p := rt; p.Kind() == reflect.Ptr { + indir++ + if indir > 100 { // insane number of indirections + return false, 0 + } + rt = p.Elem() + continue + } + break + } + // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. + if typ.Kind() != reflect.Ptr { + // Not a pointer, but does the pointer work? + if reflect.PtrTo(typ).Implements(gobEncDecType) { + return true, -1 + } + } + return false, 0 +} + +// userType returns, and saves, the information associated with user-provided type rt. +// If the user type is not valid, it calls error. +func userType(rt reflect.Type) *userTypeInfo { + ut, err := validUserType(rt) + if err != nil { + error_(err) + } + return ut +} +// A typeId represents a gob Type as an integer that can be passed on the wire. +// Internally, typeIds are used as keys to a map to recover the underlying type info. +type typeId int32 + +var nextId typeId // incremented for each new type we build +var typeLock sync.Mutex // set while building a type +const firstUserId = 64 // lowest id number granted to user + +type gobType interface { + id() typeId + setId(id typeId) + name() string + string() string // not public; only for debugging + safeString(seen map[typeId]bool) string +} + +var types = make(map[reflect.Type]gobType) +var idToType = make(map[typeId]gobType) +var builtinIdToType map[typeId]gobType // set in init() after builtins are established + +func setTypeId(typ gobType) { + nextId++ + typ.setId(nextId) + idToType[nextId] = typ +} + +func (t typeId) gobType() gobType { + if t == 0 { + return nil + } + return idToType[t] +} + +// string returns the string representation of the type associated with the typeId. +func (t typeId) string() string { + if t.gobType() == nil { + return "" + } + return t.gobType().string() +} + +// Name returns the name of the type associated with the typeId. +func (t typeId) name() string { + if t.gobType() == nil { + return "" + } + return t.gobType().name() +} + +// Common elements of all types. +type CommonType struct { + Name string + Id typeId +} + +func (t *CommonType) id() typeId { return t.Id } + +func (t *CommonType) setId(id typeId) { t.Id = id } + +func (t *CommonType) string() string { return t.Name } + +func (t *CommonType) safeString(seen map[typeId]bool) string { + return t.Name +} + +func (t *CommonType) name() string { return t.Name } + +// Create and check predefined types +// The string for tBytes is "bytes" not "[]byte" to signify its specialness. + +var ( + // Primordial types, needed during initialization. + // Always passed as pointers so the interface{} type + // goes through without losing its interfaceness. + tBool = bootstrapType("bool", (*bool)(nil), 1) + tInt = bootstrapType("int", (*int)(nil), 2) + tUint = bootstrapType("uint", (*uint)(nil), 3) + tFloat = bootstrapType("float", (*float64)(nil), 4) + tBytes = bootstrapType("bytes", (*[]byte)(nil), 5) + tString = bootstrapType("string", (*string)(nil), 6) + tComplex = bootstrapType("complex", (*complex128)(nil), 7) + tInterface = bootstrapType("interface", (*interface{})(nil), 8) + // Reserve some Ids for compatible expansion + tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9) + tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10) + tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11) + tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12) + tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13) + tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14) + tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15) +) + +// Predefined because it's needed by the Decoder +var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id +var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType) + +func init() { + // Some magic numbers to make sure there are no surprises. + checkId(16, tWireType) + checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id) + checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id) + checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id) + checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id) + checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id) + checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id) + + builtinIdToType = make(map[typeId]gobType) + for k, v := range idToType { + builtinIdToType[k] = v + } + + // Move the id space upwards to allow for growth in the predefined world + // without breaking existing files. + if nextId > firstUserId { + panic(fmt.Sprintln("nextId too large:", nextId)) + } + nextId = firstUserId + registerBasics() + wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil))) +} + +// Array type +type arrayType struct { + CommonType + Elem typeId + Len int +} + +func newArrayType(name string) *arrayType { + a := &arrayType{CommonType{Name: name}, 0, 0} + return a +} + +func (a *arrayType) init(elem gobType, len int) { + // Set our type id before evaluating the element's, in case it's our own. + setTypeId(a) + a.Elem = elem.id() + a.Len = len +} + +func (a *arrayType) safeString(seen map[typeId]bool) string { + if seen[a.Id] { + return a.Name + } + seen[a.Id] = true + return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen)) +} + +func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) } + +// GobEncoder type (something that implements the GobEncoder interface) +type gobEncoderType struct { + CommonType +} + +func newGobEncoderType(name string) *gobEncoderType { + g := &gobEncoderType{CommonType{Name: name}} + setTypeId(g) + return g +} + +func (g *gobEncoderType) safeString(seen map[typeId]bool) string { + return g.Name +} + +func (g *gobEncoderType) string() string { return g.Name } + +// Map type +type mapType struct { + CommonType + Key typeId + Elem typeId +} + +func newMapType(name string) *mapType { + m := &mapType{CommonType{Name: name}, 0, 0} + return m +} + +func (m *mapType) init(key, elem gobType) { + // Set our type id before evaluating the element's, in case it's our own. + setTypeId(m) + m.Key = key.id() + m.Elem = elem.id() +} + +func (m *mapType) safeString(seen map[typeId]bool) string { + if seen[m.Id] { + return m.Name + } + seen[m.Id] = true + key := m.Key.gobType().safeString(seen) + elem := m.Elem.gobType().safeString(seen) + return fmt.Sprintf("map[%s]%s", key, elem) +} + +func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) } + +// Slice type +type sliceType struct { + CommonType + Elem typeId +} + +func newSliceType(name string) *sliceType { + s := &sliceType{CommonType{Name: name}, 0} + return s +} + +func (s *sliceType) init(elem gobType) { + // Set our type id before evaluating the element's, in case it's our own. + setTypeId(s) + s.Elem = elem.id() +} + +func (s *sliceType) safeString(seen map[typeId]bool) string { + if seen[s.Id] { + return s.Name + } + seen[s.Id] = true + return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen)) +} + +func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) } + +// Struct type +type fieldType struct { + Name string + Id typeId +} + +type structType struct { + CommonType + Field []*fieldType +} + +func (s *structType) safeString(seen map[typeId]bool) string { + if s == nil { + return "" + } + if _, ok := seen[s.Id]; ok { + return s.Name + } + seen[s.Id] = true + str := s.Name + " = struct { " + for _, f := range s.Field { + str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen)) + } + str += "}" + return str +} + +func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) } + +func newStructType(name string) *structType { + s := &structType{CommonType{Name: name}, nil} + // For historical reasons we set the id here rather than init. + // See the comment in newTypeObject for details. + setTypeId(s) + return s +} + +// newTypeObject allocates a gobType for the reflection type rt. +// Unless ut represents a GobEncoder, rt should be the base type +// of ut. +// This is only called from the encoding side. The decoding side +// works through typeIds and userTypeInfos alone. +func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) { + // Does this type implement GobEncoder? + if ut.isGobEncoder { + return newGobEncoderType(name), nil + } + var err error + var type0, type1 gobType + defer func() { + if err != nil { + delete(types, rt) + } + }() + // Install the top-level type before the subtypes (e.g. struct before + // fields) so recursive types can be constructed safely. + switch t := rt; t.Kind() { + // All basic types are easy: they are predefined. + case reflect.Bool: + return tBool.gobType(), nil + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return tInt.gobType(), nil + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return tUint.gobType(), nil + + case reflect.Float32, reflect.Float64: + return tFloat.gobType(), nil + + case reflect.Complex64, reflect.Complex128: + return tComplex.gobType(), nil + + case reflect.String: + return tString.gobType(), nil + + case reflect.Interface: + return tInterface.gobType(), nil + + case reflect.Array: + at := newArrayType(name) + types[rt] = at + type0, err = getBaseType("", t.Elem()) + if err != nil { + return nil, err + } + // Historical aside: + // For arrays, maps, and slices, we set the type id after the elements + // are constructed. This is to retain the order of type id allocation after + // a fix made to handle recursive types, which changed the order in + // which types are built. Delaying the setting in this way preserves + // type ids while allowing recursive types to be described. Structs, + // done below, were already handling recursion correctly so they + // assign the top-level id before those of the field. + at.init(type0, t.Len()) + return at, nil + + case reflect.Map: + mt := newMapType(name) + types[rt] = mt + type0, err = getBaseType("", t.Key()) + if err != nil { + return nil, err + } + type1, err = getBaseType("", t.Elem()) + if err != nil { + return nil, err + } + mt.init(type0, type1) + return mt, nil + + case reflect.Slice: + // []byte == []uint8 is a special case + if t.Elem().Kind() == reflect.Uint8 { + return tBytes.gobType(), nil + } + st := newSliceType(name) + types[rt] = st + type0, err = getBaseType(t.Elem().Name(), t.Elem()) + if err != nil { + return nil, err + } + st.init(type0) + return st, nil + + case reflect.Struct: + st := newStructType(name) + types[rt] = st + idToType[st.id()] = st + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if !isExported(f.Name) { + continue + } + typ := userType(f.Type).base + tname := typ.Name() + if tname == "" { + t := userType(f.Type).base + tname = t.String() + } + gt, err := getBaseType(tname, f.Type) + if err != nil { + return nil, err + } + st.Field = append(st.Field, &fieldType{f.Name, gt.id()}) + } + return st, nil + + default: + return nil, errors.New("gob NewTypeObject can't handle type: " + rt.String()) + } + return nil, nil +} + +// isExported reports whether this is an exported - upper case - name. +func isExported(name string) bool { + rune, _ := utf8.DecodeRuneInString(name) + return unicode.IsUpper(rune) +} + +// getBaseType returns the Gob type describing the given reflect.Type's base type. +// typeLock must be held. +func getBaseType(name string, rt reflect.Type) (gobType, error) { + ut := userType(rt) + return getType(name, ut, ut.base) +} + +// getType returns the Gob type describing the given reflect.Type. +// Should be called only when handling GobEncoders/Decoders, +// which may be pointers. All other types are handled through the +// base type, never a pointer. +// typeLock must be held. +func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) { + typ, present := types[rt] + if present { + return typ, nil + } + typ, err := newTypeObject(name, ut, rt) + if err == nil { + types[rt] = typ + } + return typ, err +} + +func checkId(want, got typeId) { + if want != got { + fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want)) + panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string()) + } +} + +// used for building the basic types; called only from init(). the incoming +// interface always refers to a pointer. +func bootstrapType(name string, e interface{}, expect typeId) typeId { + rt := reflect.TypeOf(e).Elem() + _, present := types[rt] + if present { + panic("bootstrap type already present: " + name + ", " + rt.String()) + } + typ := &CommonType{Name: name} + types[rt] = typ + setTypeId(typ) + checkId(expect, nextId) + userType(rt) // might as well cache it now + return nextId +} + +// Representation of the information we send and receive about this type. +// Each value we send is preceded by its type definition: an encoded int. +// However, the very first time we send the value, we first send the pair +// (-id, wireType). +// For bootstrapping purposes, we assume that the recipient knows how +// to decode a wireType; it is exactly the wireType struct here, interpreted +// using the gob rules for sending a structure, except that we assume the +// ids for wireType and structType etc. are known. The relevant pieces +// are built in encode.go's init() function. +// To maintain binary compatibility, if you extend this type, always put +// the new fields last. +type wireType struct { + ArrayT *arrayType + SliceT *sliceType + StructT *structType + MapT *mapType + GobEncoderT *gobEncoderType +} + +func (w *wireType) string() string { + const unknown = "unknown type" + if w == nil { + return unknown + } + switch { + case w.ArrayT != nil: + return w.ArrayT.Name + case w.SliceT != nil: + return w.SliceT.Name + case w.StructT != nil: + return w.StructT.Name + case w.MapT != nil: + return w.MapT.Name + case w.GobEncoderT != nil: + return w.GobEncoderT.Name + } + return unknown +} + +type typeInfo struct { + id typeId + encoder *encEngine + wire *wireType +} + +var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock + +// typeLock must be held. +func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) { + rt := ut.base + if ut.isGobEncoder { + // We want the user type, not the base type. + rt = ut.user + } + info, ok := typeInfoMap[rt] + if ok { + return info, nil + } + info = new(typeInfo) + gt, err := getBaseType(rt.Name(), rt) + if err != nil { + return nil, err + } + info.id = gt.id() + + if ut.isGobEncoder { + userType, err := getType(rt.Name(), ut, rt) + if err != nil { + return nil, err + } + info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gobEncoderType)} + typeInfoMap[ut.user] = info + return info, nil + } + + t := info.id.gobType() + switch typ := rt; typ.Kind() { + case reflect.Array: + info.wire = &wireType{ArrayT: t.(*arrayType)} + case reflect.Map: + info.wire = &wireType{MapT: t.(*mapType)} + case reflect.Slice: + // []byte == []uint8 is a special case handled separately + if typ.Elem().Kind() != reflect.Uint8 { + info.wire = &wireType{SliceT: t.(*sliceType)} + } + case reflect.Struct: + info.wire = &wireType{StructT: t.(*structType)} + } + typeInfoMap[rt] = info + return info, nil +} + +// Called only when a panic is acceptable and unexpected. +func mustGetTypeInfo(rt reflect.Type) *typeInfo { + t, err := getTypeInfo(userType(rt)) + if err != nil { + panic("getTypeInfo: " + err.Error()) + } + return t +} + +// GobEncoder is the interface describing data that provides its own +// representation for encoding values for transmission to a GobDecoder. +// A type that implements GobEncoder and GobDecoder has complete +// control over the representation of its data and may therefore +// contain things such as private fields, channels, and functions, +// which are not usually transmissible in gob streams. +// +// Note: Since gobs can be stored permanently, It is good design +// to guarantee the encoding used by a GobEncoder is stable as the +// software evolves. For instance, it might make sense for GobEncode +// to include a version number in the encoding. +type GobEncoder interface { + // GobEncode returns a byte slice representing the encoding of the + // receiver for transmission to a GobDecoder, usually of the same + // concrete type. + GobEncode() ([]byte, error) +} + +// GobDecoder is the interface describing data that provides its own +// routine for decoding transmitted values sent by a GobEncoder. +type GobDecoder interface { + // GobDecode overwrites the receiver, which must be a pointer, + // with the value represented by the byte slice, which was written + // by GobEncode, usually for the same concrete type. + GobDecode([]byte) error +} + +var ( + nameToConcreteType = make(map[string]reflect.Type) + concreteTypeToName = make(map[reflect.Type]string) +) + +// RegisterName is like Register but uses the provided name rather than the +// type's default. +func RegisterName(name string, value interface{}) { + if name == "" { + // reserved for nil + panic("attempt to register empty name") + } + ut := userType(reflect.TypeOf(value)) + // Check for incompatible duplicates. The name must refer to the + // same user type, and vice versa. + if t, ok := nameToConcreteType[name]; ok && t != ut.user { + panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", name, t, ut.user)) + } + if n, ok := concreteTypeToName[ut.base]; ok && n != name { + panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", ut.user, n, name)) + } + // Store the name and type provided by the user.... + nameToConcreteType[name] = reflect.TypeOf(value) + // but the flattened type in the type table, since that's what decode needs. + concreteTypeToName[ut.base] = name +} + +// Register records a type, identified by a value for that type, under its +// internal type name. That name will identify the concrete type of a value +// sent or received as an interface variable. Only types that will be +// transferred as implementations of interface values need to be registered. +// Expecting to be used only during initialization, it panics if the mapping +// between types and names is not a bijection. +func Register(value interface{}) { + // Default to printed representation for unnamed types + rt := reflect.TypeOf(value) + name := rt.String() + + // But for named types (or pointers to them), qualify with import path. + // Dereference one pointer looking for a named type. + star := "" + if rt.Name() == "" { + if pt := rt; pt.Kind() == reflect.Ptr { + star = "*" + rt = pt + } + } + if rt.Name() != "" { + if rt.PkgPath() == "" { + name = star + rt.Name() + } else { + name = star + rt.PkgPath() + "." + rt.Name() + } + } + + RegisterName(name, value) +} + +func registerBasics() { + Register(int(0)) + Register(int8(0)) + Register(int16(0)) + Register(int32(0)) + Register(int64(0)) + Register(uint(0)) + Register(uint8(0)) + Register(uint16(0)) + Register(uint32(0)) + Register(uint64(0)) + Register(float32(0)) + Register(float64(0)) + Register(complex64(0i)) + Register(complex128(0i)) + Register(uintptr(0)) + Register(false) + Register("") + Register([]byte(nil)) + Register([]int(nil)) + Register([]int8(nil)) + Register([]int16(nil)) + Register([]int32(nil)) + Register([]int64(nil)) + Register([]uint(nil)) + Register([]uint8(nil)) + Register([]uint16(nil)) + Register([]uint32(nil)) + Register([]uint64(nil)) + Register([]float32(nil)) + Register([]float64(nil)) + Register([]complex64(nil)) + Register([]complex128(nil)) + Register([]uintptr(nil)) + Register([]bool(nil)) + Register([]string(nil)) +} diff --git a/libgo/go/encoding/gob/type_test.go b/libgo/go/encoding/gob/type_test.go new file mode 100644 index 0000000..42bdb4c --- /dev/null +++ b/libgo/go/encoding/gob/type_test.go @@ -0,0 +1,161 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import ( + "reflect" + "testing" +) + +type typeT struct { + id typeId + str string +} + +var basicTypes = []typeT{ + {tBool, "bool"}, + {tInt, "int"}, + {tUint, "uint"}, + {tFloat, "float"}, + {tBytes, "bytes"}, + {tString, "string"}, +} + +func getTypeUnlocked(name string, rt reflect.Type) gobType { + typeLock.Lock() + defer typeLock.Unlock() + t, err := getBaseType(name, rt) + if err != nil { + panic("getTypeUnlocked: " + err.Error()) + } + return t +} + +// Sanity checks +func TestBasic(t *testing.T) { + for _, tt := range basicTypes { + if tt.id.string() != tt.str { + t.Errorf("checkType: expected %q got %s", tt.str, tt.id.string()) + } + if tt.id == 0 { + t.Errorf("id for %q is zero", tt.str) + } + } +} + +// Reregister some basic types to check registration is idempotent. +func TestReregistration(t *testing.T) { + newtyp := getTypeUnlocked("int", reflect.TypeOf(int(0))) + if newtyp != tInt.gobType() { + t.Errorf("reregistration of %s got new type", newtyp.string()) + } + newtyp = getTypeUnlocked("uint", reflect.TypeOf(uint(0))) + if newtyp != tUint.gobType() { + t.Errorf("reregistration of %s got new type", newtyp.string()) + } + newtyp = getTypeUnlocked("string", reflect.TypeOf("hello")) + if newtyp != tString.gobType() { + t.Errorf("reregistration of %s got new type", newtyp.string()) + } +} + +func TestArrayType(t *testing.T) { + var a3 [3]int + a3int := getTypeUnlocked("foo", reflect.TypeOf(a3)) + newa3int := getTypeUnlocked("bar", reflect.TypeOf(a3)) + if a3int != newa3int { + t.Errorf("second registration of [3]int creates new type") + } + var a4 [4]int + a4int := getTypeUnlocked("goo", reflect.TypeOf(a4)) + if a3int == a4int { + t.Errorf("registration of [3]int creates same type as [4]int") + } + var b3 [3]bool + a3bool := getTypeUnlocked("", reflect.TypeOf(b3)) + if a3int == a3bool { + t.Errorf("registration of [3]bool creates same type as [3]int") + } + str := a3bool.string() + expected := "[3]bool" + if str != expected { + t.Errorf("array printed as %q; expected %q", str, expected) + } +} + +func TestSliceType(t *testing.T) { + var s []int + sint := getTypeUnlocked("slice", reflect.TypeOf(s)) + var news []int + newsint := getTypeUnlocked("slice1", reflect.TypeOf(news)) + if sint != newsint { + t.Errorf("second registration of []int creates new type") + } + var b []bool + sbool := getTypeUnlocked("", reflect.TypeOf(b)) + if sbool == sint { + t.Errorf("registration of []bool creates same type as []int") + } + str := sbool.string() + expected := "[]bool" + if str != expected { + t.Errorf("slice printed as %q; expected %q", str, expected) + } +} + +func TestMapType(t *testing.T) { + var m map[string]int + mapStringInt := getTypeUnlocked("map", reflect.TypeOf(m)) + var newm map[string]int + newMapStringInt := getTypeUnlocked("map1", reflect.TypeOf(newm)) + if mapStringInt != newMapStringInt { + t.Errorf("second registration of map[string]int creates new type") + } + var b map[string]bool + mapStringBool := getTypeUnlocked("", reflect.TypeOf(b)) + if mapStringBool == mapStringInt { + t.Errorf("registration of map[string]bool creates same type as map[string]int") + } + str := mapStringBool.string() + expected := "map[string]bool" + if str != expected { + t.Errorf("map printed as %q; expected %q", str, expected) + } +} + +type Bar struct { + X string +} + +// This structure has pointers and refers to itself, making it a good test case. +type Foo struct { + A int + B int32 // will become int + C string + D []byte + E *float64 // will become float64 + F ****float64 // will become float64 + G *Bar + H *Bar // should not interpolate the definition of Bar again + I *Foo // will not explode +} + +func TestStructType(t *testing.T) { + sstruct := getTypeUnlocked("Foo", reflect.TypeOf(Foo{})) + str := sstruct.string() + // If we can print it correctly, we built it correctly. + expected := "Foo = struct { A int; B int; C string; D bytes; E float; F float; G Bar = struct { X string; }; H Bar; I Foo; }" + if str != expected { + t.Errorf("struct printed as %q; expected %q", str, expected) + } +} + +// Should be OK to register the same type multiple times, as long as they're +// at the same level of indirection. +func TestRegistration(t *testing.T) { + type T struct{ a int } + Register(new(T)) + Register(new(T)) +} diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go new file mode 100644 index 0000000..41295d2 --- /dev/null +++ b/libgo/go/encoding/json/decode.go @@ -0,0 +1,939 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Represents JSON data structure using native Go types: booleans, floats, +// strings, arrays, and maps. + +package json + +import ( + "encoding/base64" + "errors" + "reflect" + "runtime" + "strconv" + "strings" + "unicode" + "unicode/utf16" + "unicode/utf8" +) + +// Unmarshal parses the JSON-encoded data and stores the result +// in the value pointed to by v. +// +// Unmarshal uses the inverse of the encodings that +// Marshal uses, allocating maps, slices, and pointers as necessary, +// with the following additional rules: +// +// To unmarshal JSON into a pointer, Unmarshal first handles the case of +// the JSON being the JSON literal null. In that case, Unmarshal sets +// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into +// the value pointed at by the pointer. If the pointer is nil, Unmarshal +// allocates a new value for it to point to. +// +// To unmarshal JSON into an interface value, Unmarshal unmarshals +// the JSON into the concrete value contained in the interface value. +// If the interface value is nil, that is, has no concrete value stored in it, +// Unmarshal stores one of these in the interface value: +// +// bool, for JSON booleans +// float64, for JSON numbers +// string, for JSON strings +// []interface{}, for JSON arrays +// map[string]interface{}, for JSON objects +// nil for JSON null +// +// If a JSON value is not appropriate for a given target type, +// or if a JSON number overflows the target type, Unmarshal +// skips that field and completes the unmarshalling as best it can. +// If no more serious errors are encountered, Unmarshal returns +// an UnmarshalTypeError describing the earliest such error. +// +func Unmarshal(data []byte, v interface{}) error { + d := new(decodeState).init(data) + + // Quick check for well-formedness. + // Avoids filling out half a data structure + // before discovering a JSON syntax error. + err := checkValid(data, &d.scan) + if err != nil { + return err + } + + return d.unmarshal(v) +} + +// Unmarshaler is the interface implemented by objects +// that can unmarshal a JSON description of themselves. +// The input can be assumed to be a valid JSON object +// encoding. UnmarshalJSON must copy the JSON data +// if it wishes to retain the data after returning. +type Unmarshaler interface { + UnmarshalJSON([]byte) error +} + +// An UnmarshalTypeError describes a JSON value that was +// not appropriate for a value of a specific Go type. +type UnmarshalTypeError struct { + Value string // description of JSON value - "bool", "array", "number -5" + Type reflect.Type // type of Go value it could not be assigned to +} + +func (e *UnmarshalTypeError) Error() string { + return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() +} + +// An UnmarshalFieldError describes a JSON object key that +// led to an unexported (and therefore unwritable) struct field. +type UnmarshalFieldError struct { + Key string + Type reflect.Type + Field reflect.StructField +} + +func (e *UnmarshalFieldError) Error() string { + return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() +} + +// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. +// (The argument to Unmarshal must be a non-nil pointer.) +type InvalidUnmarshalError struct { + Type reflect.Type +} + +func (e *InvalidUnmarshalError) Error() string { + if e.Type == nil { + return "json: Unmarshal(nil)" + } + + if e.Type.Kind() != reflect.Ptr { + return "json: Unmarshal(non-pointer " + e.Type.String() + ")" + } + return "json: Unmarshal(nil " + e.Type.String() + ")" +} + +func (d *decodeState) unmarshal(v interface{}) (err error) { + defer func() { + if r := recover(); r != nil { + if _, ok := r.(runtime.Error); ok { + panic(r) + } + err = r.(error) + } + }() + + rv := reflect.ValueOf(v) + pv := rv + if pv.Kind() != reflect.Ptr || pv.IsNil() { + return &InvalidUnmarshalError{reflect.TypeOf(v)} + } + + d.scan.reset() + // We decode rv not pv.Elem because the Unmarshaler interface + // test must be applied at the top level of the value. + d.value(rv) + return d.savedError +} + +// decodeState represents the state while decoding a JSON value. +type decodeState struct { + data []byte + off int // read offset in data + scan scanner + nextscan scanner // for calls to nextValue + savedError error + tempstr string // scratch space to avoid some allocations +} + +// errPhase is used for errors that should not happen unless +// there is a bug in the JSON decoder or something is editing +// the data slice while the decoder executes. +var errPhase = errors.New("JSON decoder out of sync - data changing underfoot?") + +func (d *decodeState) init(data []byte) *decodeState { + d.data = data + d.off = 0 + d.savedError = nil + return d +} + +// error aborts the decoding by panicking with err. +func (d *decodeState) error(err error) { + panic(err) +} + +// saveError saves the first err it is called with, +// for reporting at the end of the unmarshal. +func (d *decodeState) saveError(err error) { + if d.savedError == nil { + d.savedError = err + } +} + +// next cuts off and returns the next full JSON value in d.data[d.off:]. +// The next value is known to be an object or array, not a literal. +func (d *decodeState) next() []byte { + c := d.data[d.off] + item, rest, err := nextValue(d.data[d.off:], &d.nextscan) + if err != nil { + d.error(err) + } + d.off = len(d.data) - len(rest) + + // Our scanner has seen the opening brace/bracket + // and thinks we're still in the middle of the object. + // invent a closing brace/bracket to get it out. + if c == '{' { + d.scan.step(&d.scan, '}') + } else { + d.scan.step(&d.scan, ']') + } + + return item +} + +// scanWhile processes bytes in d.data[d.off:] until it +// receives a scan code not equal to op. +// It updates d.off and returns the new scan code. +func (d *decodeState) scanWhile(op int) int { + var newOp int + for { + if d.off >= len(d.data) { + newOp = d.scan.eof() + d.off = len(d.data) + 1 // mark processed EOF with len+1 + } else { + c := int(d.data[d.off]) + d.off++ + newOp = d.scan.step(&d.scan, c) + } + if newOp != op { + break + } + } + return newOp +} + +// value decodes a JSON value from d.data[d.off:] into the value. +// it updates d.off to point past the decoded value. +func (d *decodeState) value(v reflect.Value) { + if !v.IsValid() { + _, rest, err := nextValue(d.data[d.off:], &d.nextscan) + if err != nil { + d.error(err) + } + d.off = len(d.data) - len(rest) + + // d.scan thinks we're still at the beginning of the item. + // Feed in an empty string - the shortest, simplest value - + // so that it knows we got to the end of the value. + if d.scan.step == stateRedo { + panic("redo") + } + d.scan.step(&d.scan, '"') + d.scan.step(&d.scan, '"') + return + } + + switch op := d.scanWhile(scanSkipSpace); op { + default: + d.error(errPhase) + + case scanBeginArray: + d.array(v) + + case scanBeginObject: + d.object(v) + + case scanBeginLiteral: + d.literal(v) + } +} + +// indirect walks down v allocating pointers as needed, +// until it gets to a non-pointer. +// if it encounters an Unmarshaler, indirect stops and returns that. +// if decodingNull is true, indirect stops at the last pointer so it can be set to nil. +func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) { + // If v is a named type and is addressable, + // start with its address, so that if the type has pointer methods, + // we find them. + if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { + v = v.Addr() + } + for { + var isUnmarshaler bool + if v.Type().NumMethod() > 0 { + // Remember that this is an unmarshaler, + // but wait to return it until after allocating + // the pointer (if necessary). + _, isUnmarshaler = v.Interface().(Unmarshaler) + } + + if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() { + v = iv.Elem() + continue + } + + pv := v + if pv.Kind() != reflect.Ptr { + break + } + + if pv.Elem().Kind() != reflect.Ptr && decodingNull && pv.CanSet() { + return nil, pv + } + if pv.IsNil() { + pv.Set(reflect.New(pv.Type().Elem())) + } + if isUnmarshaler { + // Using v.Interface().(Unmarshaler) + // here means that we have to use a pointer + // as the struct field. We cannot use a value inside + // a pointer to a struct, because in that case + // v.Interface() is the value (x.f) not the pointer (&x.f). + // This is an unfortunate consequence of reflect. + // An alternative would be to look up the + // UnmarshalJSON method and return a FuncValue. + return v.Interface().(Unmarshaler), reflect.Value{} + } + v = pv.Elem() + } + return nil, v +} + +// array consumes an array from d.data[d.off-1:], decoding into the value v. +// the first byte of the array ('[') has been read already. +func (d *decodeState) array(v reflect.Value) { + // Check for unmarshaler. + unmarshaler, pv := d.indirect(v, false) + if unmarshaler != nil { + d.off-- + err := unmarshaler.UnmarshalJSON(d.next()) + if err != nil { + d.error(err) + } + return + } + v = pv + + // Decoding into nil interface? Switch to non-reflect code. + iv := v + ok := iv.Kind() == reflect.Interface + if ok { + iv.Set(reflect.ValueOf(d.arrayInterface())) + return + } + + // Check type of target. + av := v + if av.Kind() != reflect.Array && av.Kind() != reflect.Slice { + d.saveError(&UnmarshalTypeError{"array", v.Type()}) + d.off-- + d.next() + return + } + + sv := v + + i := 0 + for { + // Look ahead for ] - can only happen on first iteration. + op := d.scanWhile(scanSkipSpace) + if op == scanEndArray { + break + } + + // Back up so d.value can have the byte we just read. + d.off-- + d.scan.undo(op) + + // Get element of array, growing if necessary. + if i >= av.Cap() && sv.IsValid() { + newcap := sv.Cap() + sv.Cap()/2 + if newcap < 4 { + newcap = 4 + } + newv := reflect.MakeSlice(sv.Type(), sv.Len(), newcap) + reflect.Copy(newv, sv) + sv.Set(newv) + } + if i >= av.Len() && sv.IsValid() { + // Must be slice; gave up on array during i >= av.Cap(). + sv.SetLen(i + 1) + } + + // Decode into element. + if i < av.Len() { + d.value(av.Index(i)) + } else { + // Ran out of fixed array: skip. + d.value(reflect.Value{}) + } + i++ + + // Next token must be , or ]. + op = d.scanWhile(scanSkipSpace) + if op == scanEndArray { + break + } + if op != scanArrayValue { + d.error(errPhase) + } + } + if i < av.Len() { + if !sv.IsValid() { + // Array. Zero the rest. + z := reflect.Zero(av.Type().Elem()) + for ; i < av.Len(); i++ { + av.Index(i).Set(z) + } + } else { + sv.SetLen(i) + } + } +} + +// object consumes an object from d.data[d.off-1:], decoding into the value v. +// the first byte of the object ('{') has been read already. +func (d *decodeState) object(v reflect.Value) { + // Check for unmarshaler. + unmarshaler, pv := d.indirect(v, false) + if unmarshaler != nil { + d.off-- + err := unmarshaler.UnmarshalJSON(d.next()) + if err != nil { + d.error(err) + } + return + } + v = pv + + // Decoding into nil interface? Switch to non-reflect code. + iv := v + if iv.Kind() == reflect.Interface { + iv.Set(reflect.ValueOf(d.objectInterface())) + return + } + + // Check type of target: struct or map[string]T + var ( + mv reflect.Value + sv reflect.Value + ) + switch v.Kind() { + case reflect.Map: + // map must have string type + t := v.Type() + if t.Key() != reflect.TypeOf("") { + d.saveError(&UnmarshalTypeError{"object", v.Type()}) + break + } + mv = v + if mv.IsNil() { + mv.Set(reflect.MakeMap(t)) + } + case reflect.Struct: + sv = v + default: + d.saveError(&UnmarshalTypeError{"object", v.Type()}) + } + + if !mv.IsValid() && !sv.IsValid() { + d.off-- + d.next() // skip over { } in input + return + } + + var mapElem reflect.Value + + for { + // Read opening " of string key or closing }. + op := d.scanWhile(scanSkipSpace) + if op == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if op != scanBeginLiteral { + d.error(errPhase) + } + + // Read string key. + start := d.off - 1 + op = d.scanWhile(scanContinue) + item := d.data[start : d.off-1] + key, ok := unquote(item) + if !ok { + d.error(errPhase) + } + + // Figure out field corresponding to key. + var subv reflect.Value + destring := false // whether the value is wrapped in a string to be decoded first + + if mv.IsValid() { + elemType := mv.Type().Elem() + if !mapElem.IsValid() { + mapElem = reflect.New(elemType).Elem() + } else { + mapElem.Set(reflect.Zero(elemType)) + } + subv = mapElem + } else { + var f reflect.StructField + var ok bool + st := sv.Type() + for i := 0; i < sv.NumField(); i++ { + sf := st.Field(i) + tag := sf.Tag.Get("json") + if tag == "-" { + // Pretend this field doesn't exist. + continue + } + // First, tag match + tagName, _ := parseTag(tag) + if tagName == key { + f = sf + ok = true + break // no better match possible + } + // Second, exact field name match + if sf.Name == key { + f = sf + ok = true + } + // Third, case-insensitive field name match, + // but only if a better match hasn't already been seen + if !ok && strings.EqualFold(sf.Name, key) { + f = sf + ok = true + } + } + + // Extract value; name must be exported. + if ok { + if f.PkgPath != "" { + d.saveError(&UnmarshalFieldError{key, st, f}) + } else { + subv = sv.FieldByIndex(f.Index) + } + _, opts := parseTag(f.Tag.Get("json")) + destring = opts.Contains("string") + } + } + + // Read : before value. + if op == scanSkipSpace { + op = d.scanWhile(scanSkipSpace) + } + if op != scanObjectKey { + d.error(errPhase) + } + + // Read value. + if destring { + d.value(reflect.ValueOf(&d.tempstr)) + d.literalStore([]byte(d.tempstr), subv) + } else { + d.value(subv) + } + // Write value back to map; + // if using struct, subv points into struct already. + if mv.IsValid() { + mv.SetMapIndex(reflect.ValueOf(key), subv) + } + + // Next token must be , or }. + op = d.scanWhile(scanSkipSpace) + if op == scanEndObject { + break + } + if op != scanObjectValue { + d.error(errPhase) + } + } +} + +// literal consumes a literal from d.data[d.off-1:], decoding into the value v. +// The first byte of the literal has been read already +// (that's how the caller knows it's a literal). +func (d *decodeState) literal(v reflect.Value) { + // All bytes inside literal return scanContinue op code. + start := d.off - 1 + op := d.scanWhile(scanContinue) + + // Scan read one byte too far; back up. + d.off-- + d.scan.undo(op) + + d.literalStore(d.data[start:d.off], v) +} + +// literalStore decodes a literal stored in item into v. +func (d *decodeState) literalStore(item []byte, v reflect.Value) { + // Check for unmarshaler. + wantptr := item[0] == 'n' // null + unmarshaler, pv := d.indirect(v, wantptr) + if unmarshaler != nil { + err := unmarshaler.UnmarshalJSON(item) + if err != nil { + d.error(err) + } + return + } + v = pv + + switch c := item[0]; c { + case 'n': // null + switch v.Kind() { + default: + d.saveError(&UnmarshalTypeError{"null", v.Type()}) + case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: + v.Set(reflect.Zero(v.Type())) + } + + case 't', 'f': // true, false + value := c == 't' + switch v.Kind() { + default: + d.saveError(&UnmarshalTypeError{"bool", v.Type()}) + case reflect.Bool: + v.SetBool(value) + case reflect.Interface: + v.Set(reflect.ValueOf(value)) + } + + case '"': // string + s, ok := unquoteBytes(item) + if !ok { + d.error(errPhase) + } + switch v.Kind() { + default: + d.saveError(&UnmarshalTypeError{"string", v.Type()}) + case reflect.Slice: + if v.Type() != byteSliceType { + d.saveError(&UnmarshalTypeError{"string", v.Type()}) + break + } + b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) + n, err := base64.StdEncoding.Decode(b, s) + if err != nil { + d.saveError(err) + break + } + v.Set(reflect.ValueOf(b[0:n])) + case reflect.String: + v.SetString(string(s)) + case reflect.Interface: + v.Set(reflect.ValueOf(string(s))) + } + + default: // number + if c != '-' && (c < '0' || c > '9') { + d.error(errPhase) + } + s := string(item) + switch v.Kind() { + default: + d.error(&UnmarshalTypeError{"number", v.Type()}) + case reflect.Interface: + n, err := strconv.Atof64(s) + if err != nil { + d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) + break + } + v.Set(reflect.ValueOf(n)) + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n, err := strconv.Atoi64(s) + if err != nil || v.OverflowInt(n) { + d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) + break + } + v.SetInt(n) + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + n, err := strconv.Atoui64(s) + if err != nil || v.OverflowUint(n) { + d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) + break + } + v.SetUint(n) + + case reflect.Float32, reflect.Float64: + n, err := strconv.AtofN(s, v.Type().Bits()) + if err != nil || v.OverflowFloat(n) { + d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) + break + } + v.SetFloat(n) + } + } +} + +// The xxxInterface routines build up a value to be stored +// in an empty interface. They are not strictly necessary, +// but they avoid the weight of reflection in this common case. + +// valueInterface is like value but returns interface{} +func (d *decodeState) valueInterface() interface{} { + switch d.scanWhile(scanSkipSpace) { + default: + d.error(errPhase) + case scanBeginArray: + return d.arrayInterface() + case scanBeginObject: + return d.objectInterface() + case scanBeginLiteral: + return d.literalInterface() + } + panic("unreachable") +} + +// arrayInterface is like array but returns []interface{}. +func (d *decodeState) arrayInterface() []interface{} { + var v []interface{} + for { + // Look ahead for ] - can only happen on first iteration. + op := d.scanWhile(scanSkipSpace) + if op == scanEndArray { + break + } + + // Back up so d.value can have the byte we just read. + d.off-- + d.scan.undo(op) + + v = append(v, d.valueInterface()) + + // Next token must be , or ]. + op = d.scanWhile(scanSkipSpace) + if op == scanEndArray { + break + } + if op != scanArrayValue { + d.error(errPhase) + } + } + return v +} + +// objectInterface is like object but returns map[string]interface{}. +func (d *decodeState) objectInterface() map[string]interface{} { + m := make(map[string]interface{}) + for { + // Read opening " of string key or closing }. + op := d.scanWhile(scanSkipSpace) + if op == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if op != scanBeginLiteral { + d.error(errPhase) + } + + // Read string key. + start := d.off - 1 + op = d.scanWhile(scanContinue) + item := d.data[start : d.off-1] + key, ok := unquote(item) + if !ok { + d.error(errPhase) + } + + // Read : before value. + if op == scanSkipSpace { + op = d.scanWhile(scanSkipSpace) + } + if op != scanObjectKey { + d.error(errPhase) + } + + // Read value. + m[key] = d.valueInterface() + + // Next token must be , or }. + op = d.scanWhile(scanSkipSpace) + if op == scanEndObject { + break + } + if op != scanObjectValue { + d.error(errPhase) + } + } + return m +} + +// literalInterface is like literal but returns an interface value. +func (d *decodeState) literalInterface() interface{} { + // All bytes inside literal return scanContinue op code. + start := d.off - 1 + op := d.scanWhile(scanContinue) + + // Scan read one byte too far; back up. + d.off-- + d.scan.undo(op) + item := d.data[start:d.off] + + switch c := item[0]; c { + case 'n': // null + return nil + + case 't', 'f': // true, false + return c == 't' + + case '"': // string + s, ok := unquote(item) + if !ok { + d.error(errPhase) + } + return s + + default: // number + if c != '-' && (c < '0' || c > '9') { + d.error(errPhase) + } + n, err := strconv.Atof64(string(item)) + if err != nil { + d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)}) + } + return n + } + panic("unreachable") +} + +// getu4 decodes \uXXXX from the beginning of s, returning the hex value, +// or it returns -1. +func getu4(s []byte) rune { + if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { + return -1 + } + r, err := strconv.Btoui64(string(s[2:6]), 16) + if err != nil { + return -1 + } + return rune(r) +} + +// unquote converts a quoted JSON string literal s into an actual string t. +// The rules are different than for Go, so cannot use strconv.Unquote. +func unquote(s []byte) (t string, ok bool) { + s, ok = unquoteBytes(s) + t = string(s) + return +} + +func unquoteBytes(s []byte) (t []byte, ok bool) { + if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { + return + } + s = s[1 : len(s)-1] + + // Check for unusual characters. If there are none, + // then no unquoting is needed, so return a slice of the + // original bytes. + r := 0 + for r < len(s) { + c := s[r] + if c == '\\' || c == '"' || c < ' ' { + break + } + if c < utf8.RuneSelf { + r++ + continue + } + rr, size := utf8.DecodeRune(s[r:]) + if rr == utf8.RuneError && size == 1 { + break + } + r += size + } + if r == len(s) { + return s, true + } + + b := make([]byte, len(s)+2*utf8.UTFMax) + w := copy(b, s[0:r]) + for r < len(s) { + // Out of room? Can only happen if s is full of + // malformed UTF-8 and we're replacing each + // byte with RuneError. + if w >= len(b)-2*utf8.UTFMax { + nb := make([]byte, (len(b)+utf8.UTFMax)*2) + copy(nb, b[0:w]) + b = nb + } + switch c := s[r]; { + case c == '\\': + r++ + if r >= len(s) { + return + } + switch s[r] { + default: + return + case '"', '\\', '/', '\'': + b[w] = s[r] + r++ + w++ + case 'b': + b[w] = '\b' + r++ + w++ + case 'f': + b[w] = '\f' + r++ + w++ + case 'n': + b[w] = '\n' + r++ + w++ + case 'r': + b[w] = '\r' + r++ + w++ + case 't': + b[w] = '\t' + r++ + w++ + case 'u': + r-- + rr := getu4(s[r:]) + if rr < 0 { + return + } + r += 6 + if utf16.IsSurrogate(rr) { + rr1 := getu4(s[r:]) + if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { + // A valid pair; consume. + r += 6 + w += utf8.EncodeRune(b[w:], dec) + break + } + // Invalid surrogate; fall back to replacement rune. + rr = unicode.ReplacementChar + } + w += utf8.EncodeRune(b[w:], rr) + } + + // Quote, control characters are invalid. + case c == '"', c < ' ': + return + + // ASCII + case c < utf8.RuneSelf: + b[w] = c + r++ + w++ + + // Coerce to well-formed UTF-8. + default: + rr, size := utf8.DecodeRune(s[r:]) + r += size + w += utf8.EncodeRune(b[w:], rr) + } + } + return b[0:w], true +} diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go new file mode 100644 index 0000000..bd4326a --- /dev/null +++ b/libgo/go/encoding/json/decode_test.go @@ -0,0 +1,564 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package json + +import ( + "bytes" + "reflect" + "strings" + "testing" +) + +type T struct { + X string + Y int + Z int `json:"-"` +} + +type tx struct { + x int +} + +var txType = reflect.TypeOf((*tx)(nil)).Elem() + +// A type that can unmarshal itself. + +type unmarshaler struct { + T bool +} + +func (u *unmarshaler) UnmarshalJSON(b []byte) error { + *u = unmarshaler{true} // All we need to see that UnmarshalJson is called. + return nil +} + +type ustruct struct { + M unmarshaler +} + +var ( + um0, um1 unmarshaler // target2 of unmarshaling + ump = &um1 + umtrue = unmarshaler{true} + umslice = []unmarshaler{{true}} + umslicep = new([]unmarshaler) + umstruct = ustruct{unmarshaler{true}} +) + +type unmarshalTest struct { + in string + ptr interface{} + out interface{} + err error +} + +var unmarshalTests = []unmarshalTest{ + // basic types + {`true`, new(bool), true, nil}, + {`1`, new(int), 1, nil}, + {`1.2`, new(float64), 1.2, nil}, + {`-5`, new(int16), int16(-5), nil}, + {`"a\u1234"`, new(string), "a\u1234", nil}, + {`"http:\/\/"`, new(string), "http://", nil}, + {`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil}, + {`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil}, + {"null", new(interface{}), nil, nil}, + {`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}}, + {`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}}, + + // Z has a "-" tag. + {`{"Y": 1, "Z": 2}`, new(T), T{Y: 1}, nil}, + + // syntax errors + {`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}}, + + // composite tests + {allValueIndent, new(All), allValue, nil}, + {allValueCompact, new(All), allValue, nil}, + {allValueIndent, new(*All), &allValue, nil}, + {allValueCompact, new(*All), &allValue, nil}, + {pallValueIndent, new(All), pallValue, nil}, + {pallValueCompact, new(All), pallValue, nil}, + {pallValueIndent, new(*All), &pallValue, nil}, + {pallValueCompact, new(*All), &pallValue, nil}, + + // unmarshal interface test + {`{"T":false}`, &um0, umtrue, nil}, // use "false" so test will fail if custom unmarshaler is not called + {`{"T":false}`, &ump, &umtrue, nil}, + {`[{"T":false}]`, &umslice, umslice, nil}, + {`[{"T":false}]`, &umslicep, &umslice, nil}, + {`{"M":{"T":false}}`, &umstruct, umstruct, nil}, +} + +func TestMarshal(t *testing.T) { + b, err := Marshal(allValue) + if err != nil { + t.Fatalf("Marshal allValue: %v", err) + } + if string(b) != allValueCompact { + t.Errorf("Marshal allValueCompact") + diff(t, b, []byte(allValueCompact)) + return + } + + b, err = Marshal(pallValue) + if err != nil { + t.Fatalf("Marshal pallValue: %v", err) + } + if string(b) != pallValueCompact { + t.Errorf("Marshal pallValueCompact") + diff(t, b, []byte(pallValueCompact)) + return + } +} + +func TestMarshalBadUTF8(t *testing.T) { + s := "hello\xffworld" + b, err := Marshal(s) + if err == nil { + t.Fatal("Marshal bad UTF8: no error") + } + if len(b) != 0 { + t.Fatal("Marshal returned data") + } + if _, ok := err.(*InvalidUTF8Error); !ok { + t.Fatalf("Marshal did not return InvalidUTF8Error: %T %v", err, err) + } +} + +func TestUnmarshal(t *testing.T) { + for i, tt := range unmarshalTests { + var scan scanner + in := []byte(tt.in) + if err := checkValid(in, &scan); err != nil { + if !reflect.DeepEqual(err, tt.err) { + t.Errorf("#%d: checkValid: %#v", i, err) + continue + } + } + if tt.ptr == nil { + continue + } + // v = new(right-type) + v := reflect.New(reflect.TypeOf(tt.ptr).Elem()) + if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) { + t.Errorf("#%d: %v want %v", i, err, tt.err) + continue + } + if !reflect.DeepEqual(v.Elem().Interface(), tt.out) { + t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out) + data, _ := Marshal(v.Elem().Interface()) + println(string(data)) + data, _ = Marshal(tt.out) + println(string(data)) + continue + } + } +} + +func TestUnmarshalMarshal(t *testing.T) { + initBig() + var v interface{} + if err := Unmarshal(jsonBig, &v); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + b, err := Marshal(v) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + if bytes.Compare(jsonBig, b) != 0 { + t.Errorf("Marshal jsonBig") + diff(t, b, jsonBig) + return + } +} + +func TestLargeByteSlice(t *testing.T) { + s0 := make([]byte, 2000) + for i := range s0 { + s0[i] = byte(i) + } + b, err := Marshal(s0) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + var s1 []byte + if err := Unmarshal(b, &s1); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + if bytes.Compare(s0, s1) != 0 { + t.Errorf("Marshal large byte slice") + diff(t, s0, s1) + } +} + +type Xint struct { + X int +} + +func TestUnmarshalInterface(t *testing.T) { + var xint Xint + var i interface{} = &xint + if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + if xint.X != 1 { + t.Fatalf("Did not write to xint") + } +} + +func TestUnmarshalPtrPtr(t *testing.T) { + var xint Xint + pxint := &xint + if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + if xint.X != 1 { + t.Fatalf("Did not write to xint") + } +} + +func TestEscape(t *testing.T) { + const input = `"foobar"` + const expected = `"\"foobar\"\u003chtml\u003e"` + b, err := Marshal(input) + if err != nil { + t.Fatalf("Marshal error: %v", err) + } + if s := string(b); s != expected { + t.Errorf("Encoding of [%s] was [%s], want [%s]", input, s, expected) + } +} + +func TestHTMLEscape(t *testing.T) { + b, err := MarshalForHTML("foobarbaz<>&quux") + if err != nil { + t.Fatalf("MarshalForHTML error: %v", err) + } + if !bytes.Equal(b, []byte(`"foobarbaz\u003c\u003e\u0026quux"`)) { + t.Fatalf("Unexpected encoding of \"<>&\": %s", b) + } +} + +func noSpace(c rune) rune { + if isSpace(c) { + return -1 + } + return c +} + +type All struct { + Bool bool + Int int + Int8 int8 + Int16 int16 + Int32 int32 + Int64 int64 + Uint uint + Uint8 uint8 + Uint16 uint16 + Uint32 uint32 + Uint64 uint64 + Uintptr uintptr + Float32 float32 + Float64 float64 + + Foo string `json:"bar"` + Foo2 string `json:"bar2,dummyopt"` + + IntStr int64 `json:",string"` + + PBool *bool + PInt *int + PInt8 *int8 + PInt16 *int16 + PInt32 *int32 + PInt64 *int64 + PUint *uint + PUint8 *uint8 + PUint16 *uint16 + PUint32 *uint32 + PUint64 *uint64 + PUintptr *uintptr + PFloat32 *float32 + PFloat64 *float64 + + String string + PString *string + + Map map[string]Small + MapP map[string]*Small + PMap *map[string]Small + PMapP *map[string]*Small + + EmptyMap map[string]Small + NilMap map[string]Small + + Slice []Small + SliceP []*Small + PSlice *[]Small + PSliceP *[]*Small + + EmptySlice []Small + NilSlice []Small + + StringSlice []string + ByteSlice []byte + + Small Small + PSmall *Small + PPSmall **Small + + Interface interface{} + PInterface *interface{} + + unexported int +} + +type Small struct { + Tag string +} + +var allValue = All{ + Bool: true, + Int: 2, + Int8: 3, + Int16: 4, + Int32: 5, + Int64: 6, + Uint: 7, + Uint8: 8, + Uint16: 9, + Uint32: 10, + Uint64: 11, + Uintptr: 12, + Float32: 14.1, + Float64: 15.1, + Foo: "foo", + Foo2: "foo2", + IntStr: 42, + String: "16", + Map: map[string]Small{ + "17": {Tag: "tag17"}, + "18": {Tag: "tag18"}, + }, + MapP: map[string]*Small{ + "19": &Small{Tag: "tag19"}, + "20": nil, + }, + EmptyMap: map[string]Small{}, + Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}}, + SliceP: []*Small{&Small{Tag: "tag22"}, nil, &Small{Tag: "tag23"}}, + EmptySlice: []Small{}, + StringSlice: []string{"str24", "str25", "str26"}, + ByteSlice: []byte{27, 28, 29}, + Small: Small{Tag: "tag30"}, + PSmall: &Small{Tag: "tag31"}, + Interface: 5.2, +} + +var pallValue = All{ + PBool: &allValue.Bool, + PInt: &allValue.Int, + PInt8: &allValue.Int8, + PInt16: &allValue.Int16, + PInt32: &allValue.Int32, + PInt64: &allValue.Int64, + PUint: &allValue.Uint, + PUint8: &allValue.Uint8, + PUint16: &allValue.Uint16, + PUint32: &allValue.Uint32, + PUint64: &allValue.Uint64, + PUintptr: &allValue.Uintptr, + PFloat32: &allValue.Float32, + PFloat64: &allValue.Float64, + PString: &allValue.String, + PMap: &allValue.Map, + PMapP: &allValue.MapP, + PSlice: &allValue.Slice, + PSliceP: &allValue.SliceP, + PPSmall: &allValue.PSmall, + PInterface: &allValue.Interface, +} + +var allValueIndent = `{ + "Bool": true, + "Int": 2, + "Int8": 3, + "Int16": 4, + "Int32": 5, + "Int64": 6, + "Uint": 7, + "Uint8": 8, + "Uint16": 9, + "Uint32": 10, + "Uint64": 11, + "Uintptr": 12, + "Float32": 14.1, + "Float64": 15.1, + "bar": "foo", + "bar2": "foo2", + "IntStr": "42", + "PBool": null, + "PInt": null, + "PInt8": null, + "PInt16": null, + "PInt32": null, + "PInt64": null, + "PUint": null, + "PUint8": null, + "PUint16": null, + "PUint32": null, + "PUint64": null, + "PUintptr": null, + "PFloat32": null, + "PFloat64": null, + "String": "16", + "PString": null, + "Map": { + "17": { + "Tag": "tag17" + }, + "18": { + "Tag": "tag18" + } + }, + "MapP": { + "19": { + "Tag": "tag19" + }, + "20": null + }, + "PMap": null, + "PMapP": null, + "EmptyMap": {}, + "NilMap": null, + "Slice": [ + { + "Tag": "tag20" + }, + { + "Tag": "tag21" + } + ], + "SliceP": [ + { + "Tag": "tag22" + }, + null, + { + "Tag": "tag23" + } + ], + "PSlice": null, + "PSliceP": null, + "EmptySlice": [], + "NilSlice": null, + "StringSlice": [ + "str24", + "str25", + "str26" + ], + "ByteSlice": "Gxwd", + "Small": { + "Tag": "tag30" + }, + "PSmall": { + "Tag": "tag31" + }, + "PPSmall": null, + "Interface": 5.2, + "PInterface": null +}` + +var allValueCompact = strings.Map(noSpace, allValueIndent) + +var pallValueIndent = `{ + "Bool": false, + "Int": 0, + "Int8": 0, + "Int16": 0, + "Int32": 0, + "Int64": 0, + "Uint": 0, + "Uint8": 0, + "Uint16": 0, + "Uint32": 0, + "Uint64": 0, + "Uintptr": 0, + "Float32": 0, + "Float64": 0, + "bar": "", + "bar2": "", + "IntStr": "0", + "PBool": true, + "PInt": 2, + "PInt8": 3, + "PInt16": 4, + "PInt32": 5, + "PInt64": 6, + "PUint": 7, + "PUint8": 8, + "PUint16": 9, + "PUint32": 10, + "PUint64": 11, + "PUintptr": 12, + "PFloat32": 14.1, + "PFloat64": 15.1, + "String": "", + "PString": "16", + "Map": null, + "MapP": null, + "PMap": { + "17": { + "Tag": "tag17" + }, + "18": { + "Tag": "tag18" + } + }, + "PMapP": { + "19": { + "Tag": "tag19" + }, + "20": null + }, + "EmptyMap": null, + "NilMap": null, + "Slice": null, + "SliceP": null, + "PSlice": [ + { + "Tag": "tag20" + }, + { + "Tag": "tag21" + } + ], + "PSliceP": [ + { + "Tag": "tag22" + }, + null, + { + "Tag": "tag23" + } + ], + "EmptySlice": null, + "NilSlice": null, + "StringSlice": null, + "ByteSlice": null, + "Small": { + "Tag": "" + }, + "PSmall": null, + "PPSmall": { + "Tag": "tag31" + }, + "Interface": null, + "PInterface": 5.2 +}` + +var pallValueCompact = strings.Map(noSpace, pallValueIndent) diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go new file mode 100644 index 0000000..35964c5 --- /dev/null +++ b/libgo/go/encoding/json/encode.go @@ -0,0 +1,472 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package json implements encoding and decoding of JSON objects as defined in +// RFC 4627. +// +// See "JSON and Go" for an introduction to this package: +// http://blog.golang.org/2011/01/json-and-go.html +package json + +import ( + "bytes" + "encoding/base64" + "reflect" + "runtime" + "sort" + "strconv" + "unicode" + "unicode/utf8" +) + +// Marshal returns the JSON encoding of v. +// +// Marshal traverses the value v recursively. +// If an encountered value implements the Marshaler interface +// and is not a nil pointer, Marshal calls its MarshalJSON method +// to produce JSON. The nil pointer exception is not strictly necessary +// but mimics a similar, necessary exception in the behavior of +// UnmarshalJSON. +// +// Otherwise, Marshal uses the following type-dependent default encodings: +// +// Boolean values encode as JSON booleans. +// +// Floating point and integer values encode as JSON numbers. +// +// String values encode as JSON strings, with each invalid UTF-8 sequence +// replaced by the encoding of the Unicode replacement character U+FFFD. +// +// Array and slice values encode as JSON arrays, except that +// []byte encodes as a base64-encoded string. +// +// Struct values encode as JSON objects. Each exported struct field +// becomes a member of the object unless +// - the field's tag is "-", or +// - the field is empty and its tag specifies the "omitempty" option. +// The empty values are false, 0, any +// nil pointer or interface value, and any array, slice, map, or string of +// length zero. The object's default key string is the struct field name +// but can be specified in the struct field's tag value. The "json" key in +// struct field's tag value is the key name, followed by an optional comma +// and options. Examples: +// +// // Field is ignored by this package. +// Field int `json:"-"` +// +// // Field appears in JSON as key "myName". +// Field int `json:"myName"` +// +// // Field appears in JSON as key "myName" and +// // the field is omitted from the object if its value is empty, +// // as defined above. +// Field int `json:"myName,omitempty"` +// +// // Field appears in JSON as key "Field" (the default), but +// // the field is skipped if empty. +// // Note the leading comma. +// Field int `json:",omitempty"` +// +// The "string" option signals that a field is stored as JSON inside a +// JSON-encoded string. This extra level of encoding is sometimes +// used when communicating with JavaScript programs: +// +// Int64String int64 `json:",string"` +// +// The key name will be used if it's a non-empty string consisting of +// only Unicode letters, digits, dollar signs, hyphens, and underscores. +// +// Map values encode as JSON objects. +// The map's key type must be string; the object keys are used directly +// as map keys. +// +// Pointer values encode as the value pointed to. +// A nil pointer encodes as the null JSON object. +// +// Interface values encode as the value contained in the interface. +// A nil interface value encodes as the null JSON object. +// +// Channel, complex, and function values cannot be encoded in JSON. +// Attempting to encode such a value causes Marshal to return +// an InvalidTypeError. +// +// JSON cannot represent cyclic data structures and Marshal does not +// handle them. Passing cyclic structures to Marshal will result in +// an infinite recursion. +// +func Marshal(v interface{}) ([]byte, error) { + e := &encodeState{} + err := e.marshal(v) + if err != nil { + return nil, err + } + return e.Bytes(), nil +} + +// MarshalIndent is like Marshal but applies Indent to format the output. +func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { + b, err := Marshal(v) + if err != nil { + return nil, err + } + var buf bytes.Buffer + err = Indent(&buf, b, prefix, indent) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// MarshalForHTML is like Marshal but applies HTMLEscape to the output. +func MarshalForHTML(v interface{}) ([]byte, error) { + b, err := Marshal(v) + if err != nil { + return nil, err + } + var buf bytes.Buffer + HTMLEscape(&buf, b) + return buf.Bytes(), nil +} + +// HTMLEscape appends to dst the JSON-encoded src with <, >, and & +// characters inside string literals changed to \u003c, \u003e, \u0026 +// so that the JSON will be safe to embed inside HTML ") - -produces - - Hello, ! - -but after securing with EscapeSet like this, - - tmpls, err := EscapeSet(tmpls, "t") - tmpls.Execute(out, "t", ...) - -produces the safe, escaped HTML output - - Hello, <script>alert('you have been pwned')</script>! - - -Contexts - -EscapeSet understands HTML, CSS, JavaScript, and URIs. It adds sanitizing -functions to each simple action pipeline, so given the excerpt - - {{.}} - -EscapeSet will rewrite each {{.}} to add escaping functions where necessary, -in this case, - - {{. | html}} - - -Errors - -See the documentation of ErrorCode for details. - - -A fuller picture - -The rest of this package comment may be skipped on first reading; it includes -details necessary to understand escaping contexts and error messages. Most users -will not need to understand these details. - - -Contexts - -Assuming {{.}} is `O'Reilly: How are you?`, the table below shows -how {{.}} appears when used in the context to the left. - -Context {{.}} After -{{.}} O'Reilly: How are <i>you</i>? - O'Reilly: How are you? - O'Reilly: How are %3ci%3eyou%3c/i%3e? - O'Reilly%3a%20How%20are%3ci%3e...%3f - O\x27Reilly: How are \x3ci\x3eyou...? - "O\x27Reilly: How are \x3ci\x3eyou...?" - O\x27Reilly: How are \x3ci\x3eyou...\x3f - -If used in an unsafe context, then the value might be filtered out: - -Context {{.}} After - #ZgotmplZ - -since "O'Reilly:" is not an allowed protocol like "http:". - - -If {{.}} is the innocuous word, `left`, then it can appear more widely, - -Context {{.}} After -{{.}} left - left - left - left - left - left - left - left - left - -Non-string values can be used in JavaScript contexts. -If {{.}} is - - []struct{A,B string}{ "foo", "bar" } - -in the escaped template - - - -then the template output is - - - -See package json to understand how non-string content is marshalled for -embedding in JavaScript contexts. - - -Typed Strings - -By default, EscapeSet assumes all pipelines produce a plain text string. It -adds escaping pipeline stages necessary to correctly and safely embed that -plain text string in the appropriate context. - -When a data value is not plain text, you can make sure it is not over-escaped -by marking it with its type. - -Types HTML, JS, URL, and others from content.go can carry safe content that is -exempted from escaping. - -The template - - Hello, {{.}}! - -can be invoked with - - tmpl.Execute(out, HTML(`World`)) - -to produce - - Hello, World! - -instead of the - - Hello, <b>World<b>! - -that would have been produced if {{.}} was a regular string. - - -Security Model - -http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition defines "safe" as used by this package. - -This package assumes that template authors are trusted, that Execute's data -parameter is not, and seeks to preserve the properties below in the face -of untrusted data: - -Structure Preservation Property -"... when a template author writes an HTML tag in a safe templating language, -the browser will interpret the corresponding portion of the output as a tag -regardless of the values of untrusted data, and similarly for other structures -such as attribute boundaries and JS and CSS string boundaries." - -Code Effect Property -"... only code specified by the template author should run as a result of -injecting the template output into a page and all code specified by the -template author should run as a result of the same." - -Least Surprise Property -"A developer (or code reviewer) familiar with HTML, CSS, and JavaScript; -who knows that EscapeSet is applied should be able to look at a {{.}} -and correctly infer what sanitization happens." -*/ -package html diff --git a/libgo/go/exp/template/html/error.go b/libgo/go/exp/template/html/error.go deleted file mode 100644 index 22fca9e..0000000 --- a/libgo/go/exp/template/html/error.go +++ /dev/null @@ -1,213 +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 html - -import ( - "fmt" -) - -// Error describes a problem encountered during template Escaping. -type Error struct { - // ErrorCode describes the kind of error. - ErrorCode ErrorCode - // Name is the name of the template in which the error was encountered. - Name string - // Line is the line number of the error in the template source or 0. - Line int - // Description is a human-readable description of the problem. - Description string -} - -// ErrorCode is a code for a kind of error. -type ErrorCode int - -// We define codes for each error that manifests while escaping templates, but -// escaped templates may also fail at runtime. -// -// Output: "ZgotmplZ" -// Example: -// -// where {{.X}} evaluates to `javascript:...` -// Discussion: -// "ZgotmplZ" is a special value that indicates that unsafe content reached a -// CSS or URL context at runtime. The output of the example will be -// -// If the data comes from a trusted source, use content types to exempt it -// from filtering: URL(`javascript:...`). -const ( - // OK indicates the lack of an error. - OK ErrorCode = iota - - // ErrAmbigContext: "... appears in an ambiguous URL context" - // Example: - // - // Discussion: - // {{.X}} is in an ambiguous URL context since, depending on {{.C}}, - // it may be either a URL suffix or a query parameter. - // Moving {{.X}} into the condition removes the ambiguity: - // - ErrAmbigContext - - // ErrBadHTML: "expected space, attr name, or end of tag, but got ...", - // "... in unquoted attr", "... in attribute name" - // Example: - // - // - //
- //
{{end}} - // {{define "attrs"}}href="{{.URL}}"{{end}} - // Discussion: - // EscapeSet looks through template calls to compute the context. - // Here the {{.URL}} in "attrs" must be treated as a URL when called - // from "main", but if "attrs" is not in set when - // EscapeSet(&set, "main") is called, this error will arise. - ErrNoSuchTemplate - - // ErrOutputContext: "cannot compute output context for template ..." - // Examples: - // {{define "t"}}{{if .T}}{{template "t" .T}}{{end}}{{.H}}",{{end}} - // Discussion: - // A recursive template does not end in the same context in which it - // starts, and a reliable output context cannot be computed. - // Look for typos in the named template. - // If the template should not be called in the named start context, - // look for calls to that template in unexpected contexts. - // Maybe refactor recursive templates to not be recursive. - ErrOutputContext - - // ErrPartialCharset: "unfinished JS regexp charset in ..." - // Example: - // - // Discussion: - // EscapeSet does not support interpolation into regular expression - // literal character sets. - ErrPartialCharset - - // ErrPartialEscape: "unfinished escape sequence in ..." - // Example: - // - // Discussion: - // EscapeSet does not support actions following a backslash. - // This is usually an error and there are better solutions; for - // our example - // - // should work, and if {{.X}} is a partial escape sequence such as - // "xA0", mark the whole sequence as safe content: JSStr(`\xA0`) - ErrPartialEscape - - // ErrRangeLoopReentry: "on range loop re-entry: ..." - // Example: - // {{range .}}

tag is missing a '>'. - // EscapeSet cannot tell whether {{.}} is meant to be an HTML class or - // the content of a broken

element and complains because the - // second iteration would produce something like - // - //

- // {{if .C}}var x = 1{{end}} - // /-{{.N}}/i.test(x) ? doThis : doThat(); - // - // Discussion: - // The example above could produce `var x = 1/-2/i.test(s)...` - // in which the first '/' is a mathematical division operator or it - // could produce `/-2/i.test(s)` in which the first '/' starts a - // regexp literal. - // Look for missing semicolons inside branches, and maybe add - // parentheses to make it clear which interpretation you intend. - ErrSlashAmbig -) - -func (e *Error) Error() string { - if e.Line != 0 { - return fmt.Sprintf("exp/template/html:%s:%d: %s", e.Name, e.Line, e.Description) - } else if e.Name != "" { - return fmt.Sprintf("exp/template/html:%s: %s", e.Name, e.Description) - } - return "exp/template/html: " + e.Description -} - -// errorf creates an error given a format string f and args. -// The template Name still needs to be supplied. -func errorf(k ErrorCode, line int, f string, args ...interface{}) *Error { - return &Error{k, "", line, fmt.Sprintf(f, args...)} -} diff --git a/libgo/go/exp/template/html/escape.go b/libgo/go/exp/template/html/escape.go deleted file mode 100644 index 28615a9..0000000 --- a/libgo/go/exp/template/html/escape.go +++ /dev/null @@ -1,760 +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 html - -import ( - "bytes" - "fmt" - "html" - "template" - "template/parse" -) - -// Escape rewrites each action in the template to guarantee that the output is -// properly escaped. -func Escape(t *template.Template) (*template.Template, error) { - var s template.Set - s.Add(t) - if _, err := EscapeSet(&s, t.Name()); err != nil { - return nil, err - } - // TODO: if s contains cloned dependencies due to self-recursion - // cross-context, error out. - return t, nil -} - -// EscapeSet rewrites the template set to guarantee that the output of any of -// the named templates is properly escaped. -// Names should include the names of all templates that might be Executed but -// need not include helper templates. -// If no error is returned, then the named templates have been modified. -// Otherwise the named templates have been rendered unusable. -func EscapeSet(s *template.Set, names ...string) (*template.Set, error) { - if len(names) == 0 { - // TODO: Maybe add a method to Set to enumerate template names - // and use those instead. - return nil, &Error{ErrNoNames, "", 0, "must specify names of top level templates"} - } - e := newEscaper(s) - for _, name := range names { - c, _ := e.escapeTree(context{}, name, 0) - var err error - if c.err != nil { - err, c.err.Name = c.err, name - } else if c.state != stateText { - err = &Error{ErrEndContext, name, 0, fmt.Sprintf("ends in a non-text context: %v", c)} - } - if err != nil { - // Prevent execution of unsafe templates. - for _, name := range names { - if t := s.Template(name); t != nil { - t.Tree = nil - } - } - return nil, err - } - } - e.commit() - return s, nil -} - -// funcMap maps command names to functions that render their inputs safe. -var funcMap = template.FuncMap{ - "exp_template_html_attrescaper": attrEscaper, - "exp_template_html_commentescaper": commentEscaper, - "exp_template_html_cssescaper": cssEscaper, - "exp_template_html_cssvaluefilter": cssValueFilter, - "exp_template_html_htmlnamefilter": htmlNameFilter, - "exp_template_html_htmlescaper": htmlEscaper, - "exp_template_html_jsregexpescaper": jsRegexpEscaper, - "exp_template_html_jsstrescaper": jsStrEscaper, - "exp_template_html_jsvalescaper": jsValEscaper, - "exp_template_html_nospaceescaper": htmlNospaceEscaper, - "exp_template_html_rcdataescaper": rcdataEscaper, - "exp_template_html_urlescaper": urlEscaper, - "exp_template_html_urlfilter": urlFilter, - "exp_template_html_urlnormalizer": urlNormalizer, -} - -// equivEscapers matches contextual escapers to equivalent template builtins. -var equivEscapers = map[string]string{ - "exp_template_html_attrescaper": "html", - "exp_template_html_htmlescaper": "html", - "exp_template_html_nospaceescaper": "html", - "exp_template_html_rcdataescaper": "html", - "exp_template_html_urlescaper": "urlquery", - "exp_template_html_urlnormalizer": "urlquery", -} - -// escaper collects type inferences about templates and changes needed to make -// templates injection safe. -type escaper struct { - // set is the template set being escaped. - set *template.Set - // output[templateName] is the output context for a templateName that - // has been mangled to include its input context. - output map[string]context - // derived[c.mangle(name)] maps to a template derived from the template - // named name templateName for the start context c. - derived map[string]*template.Template - // called[templateName] is a set of called mangled template names. - called map[string]bool - // xxxNodeEdits are the accumulated edits to apply during commit. - // Such edits are not applied immediately in case a template set - // executes a given template in different escaping contexts. - actionNodeEdits map[*parse.ActionNode][]string - templateNodeEdits map[*parse.TemplateNode]string - textNodeEdits map[*parse.TextNode][]byte -} - -// newEscaper creates a blank escaper for the given set. -func newEscaper(s *template.Set) *escaper { - return &escaper{ - s, - map[string]context{}, - map[string]*template.Template{}, - map[string]bool{}, - map[*parse.ActionNode][]string{}, - map[*parse.TemplateNode]string{}, - map[*parse.TextNode][]byte{}, - } -} - -// filterFailsafe is an innocuous word that is emitted in place of unsafe values -// by sanitizer functions. It is not a keyword in any programming language, -// contains no special characters, is not empty, and when it appears in output -// it is distinct enough that a developer can find the source of the problem -// via a search engine. -const filterFailsafe = "ZgotmplZ" - -// escape escapes a template node. -func (e *escaper) escape(c context, n parse.Node) context { - switch n := n.(type) { - case *parse.ActionNode: - return e.escapeAction(c, n) - case *parse.IfNode: - return e.escapeBranch(c, &n.BranchNode, "if") - case *parse.ListNode: - return e.escapeList(c, n) - case *parse.RangeNode: - return e.escapeBranch(c, &n.BranchNode, "range") - case *parse.TemplateNode: - return e.escapeTemplate(c, n) - case *parse.TextNode: - return e.escapeText(c, n) - case *parse.WithNode: - return e.escapeBranch(c, &n.BranchNode, "with") - } - panic("escaping " + n.String() + " is unimplemented") -} - -// escapeAction escapes an action template node. -func (e *escaper) escapeAction(c context, n *parse.ActionNode) context { - if len(n.Pipe.Decl) != 0 { - // A local variable assignment, not an interpolation. - return c - } - c = nudge(c) - s := make([]string, 0, 3) - switch c.state { - case stateError: - return c - case stateURL, stateCSSDqStr, stateCSSSqStr, stateCSSDqURL, stateCSSSqURL, stateCSSURL: - switch c.urlPart { - case urlPartNone: - s = append(s, "exp_template_html_urlfilter") - fallthrough - case urlPartPreQuery: - switch c.state { - case stateCSSDqStr, stateCSSSqStr: - s = append(s, "exp_template_html_cssescaper") - default: - s = append(s, "exp_template_html_urlnormalizer") - } - case urlPartQueryOrFrag: - s = append(s, "exp_template_html_urlescaper") - case urlPartUnknown: - return context{ - state: stateError, - err: errorf(ErrAmbigContext, n.Line, "%s appears in an ambiguous URL context", n), - } - default: - panic(c.urlPart.String()) - } - case stateJS: - s = append(s, "exp_template_html_jsvalescaper") - // A slash after a value starts a div operator. - c.jsCtx = jsCtxDivOp - case stateJSDqStr, stateJSSqStr: - s = append(s, "exp_template_html_jsstrescaper") - case stateJSRegexp: - s = append(s, "exp_template_html_jsregexpescaper") - case stateCSS: - s = append(s, "exp_template_html_cssvaluefilter") - case stateText: - s = append(s, "exp_template_html_htmlescaper") - case stateRCDATA: - s = append(s, "exp_template_html_rcdataescaper") - case stateAttr: - // Handled below in delim check. - case stateAttrName, stateTag: - c.state = stateAttrName - s = append(s, "exp_template_html_htmlnamefilter") - default: - if isComment(c.state) { - s = append(s, "exp_template_html_commentescaper") - } else { - panic("unexpected state " + c.state.String()) - } - } - switch c.delim { - case delimNone: - // No extra-escaping needed for raw text content. - case delimSpaceOrTagEnd: - s = append(s, "exp_template_html_nospaceescaper") - default: - s = append(s, "exp_template_html_attrescaper") - } - e.editActionNode(n, s) - return c -} - -// ensurePipelineContains ensures that the pipeline has commands with -// the identifiers in s in order. -// If the pipeline already has some of the sanitizers, do not interfere. -// For example, if p is (.X | html) and s is ["escapeJSVal", "html"] then it -// has one matching, "html", and one to insert, "escapeJSVal", to produce -// (.X | escapeJSVal | html). -func ensurePipelineContains(p *parse.PipeNode, s []string) { - if len(s) == 0 { - return - } - n := len(p.Cmds) - // Find the identifiers at the end of the command chain. - idents := p.Cmds - for i := n - 1; i >= 0; i-- { - if cmd := p.Cmds[i]; len(cmd.Args) != 0 { - if id, ok := cmd.Args[0].(*parse.IdentifierNode); ok { - if id.Ident == "noescape" { - return - } - continue - } - } - idents = p.Cmds[i+1:] - } - dups := 0 - for _, id := range idents { - if escFnsEq(s[dups], (id.Args[0].(*parse.IdentifierNode)).Ident) { - dups++ - if dups == len(s) { - return - } - } - } - newCmds := make([]*parse.CommandNode, n-len(idents), n+len(s)-dups) - copy(newCmds, p.Cmds) - // Merge existing identifier commands with the sanitizers needed. - for _, id := range idents { - i := indexOfStr((id.Args[0].(*parse.IdentifierNode)).Ident, s, escFnsEq) - if i != -1 { - for _, name := range s[:i] { - newCmds = appendCmd(newCmds, newIdentCmd(name)) - } - s = s[i+1:] - } - newCmds = appendCmd(newCmds, id) - } - // Create any remaining sanitizers. - for _, name := range s { - newCmds = appendCmd(newCmds, newIdentCmd(name)) - } - p.Cmds = newCmds -} - -// redundantFuncs[a][b] implies that funcMap[b](funcMap[a](x)) == funcMap[a](x) -// for all x. -var redundantFuncs = map[string]map[string]bool{ - "exp_template_html_commentescaper": { - "exp_template_html_attrescaper": true, - "exp_template_html_nospaceescaper": true, - "exp_template_html_htmlescaper": true, - }, - "exp_template_html_cssescaper": { - "exp_template_html_attrescaper": true, - }, - "exp_template_html_jsregexpescaper": { - "exp_template_html_attrescaper": true, - }, - "exp_template_html_jsstrescaper": { - "exp_template_html_attrescaper": true, - }, - "exp_template_html_urlescaper": { - "exp_template_html_urlnormalizer": true, - }, -} - -// appendCmd appends the given command to the end of the command pipeline -// unless it is redundant with the last command. -func appendCmd(cmds []*parse.CommandNode, cmd *parse.CommandNode) []*parse.CommandNode { - if n := len(cmds); n != 0 { - last, ok := cmds[n-1].Args[0].(*parse.IdentifierNode) - next, _ := cmd.Args[0].(*parse.IdentifierNode) - if ok && redundantFuncs[last.Ident][next.Ident] { - return cmds - } - } - return append(cmds, cmd) -} - -// indexOfStr is the first i such that eq(s, strs[i]) or -1 if s was not found. -func indexOfStr(s string, strs []string, eq func(a, b string) bool) int { - for i, t := range strs { - if eq(s, t) { - return i - } - } - return -1 -} - -// escFnsEq returns whether the two escaping functions are equivalent. -func escFnsEq(a, b string) bool { - if e := equivEscapers[a]; e != "" { - a = e - } - if e := equivEscapers[b]; e != "" { - b = e - } - return a == b -} - -// newIdentCmd produces a command containing a single identifier node. -func newIdentCmd(identifier string) *parse.CommandNode { - return &parse.CommandNode{ - NodeType: parse.NodeCommand, - Args: []parse.Node{parse.NewIdentifier(identifier)}, - } -} - -// nudge returns the context that would result from following empty string -// transitions from the input context. -// For example, parsing: -// `90% of the time. - e.output[t.Name()] = c - return e.escapeListConditionally(c, t.Tree.Root, filter) -} - -// delimEnds maps each delim to a string of characters that terminate it. -var delimEnds = [...]string{ - delimDoubleQuote: `"`, - delimSingleQuote: "'", - // Determined empirically by running the below in various browsers. - // var div = document.createElement("DIV"); - // for (var i = 0; i < 0x10000; ++i) { - // div.innerHTML = ""; - // if (div.getElementsByTagName("SPAN")[0].title.indexOf("bar") < 0) - // document.write("

U+" + i.toString(16)); - // } - delimSpaceOrTagEnd: " \t\n\f\r>", -} - -var doctypeBytes = []byte("= i; j-- { - if s[j] == '<' { - end = j - break - } - } - } - for j := i; j < end; j++ { - if s[j] == '<' && !bytes.HasPrefix(s[j:], doctypeBytes) { - b.Write(s[written:j]) - b.WriteString("<") - written = j + 1 - } - } - } else if isComment(c.state) && c.delim == delimNone { - switch c.state { - case stateJSBlockCmt: - // http://es5.github.com/#x7.4: - // "Comments behave like white space and are - // discarded except that, if a MultiLineComment - // contains a line terminator character, then - // the entire comment is considered to be a - // LineTerminator for purposes of parsing by - // the syntactic grammar." - if bytes.IndexAny(s[written:i1], "\n\r\u2028\u2029") != -1 { - b.WriteByte('\n') - } else { - b.WriteByte(' ') - } - case stateCSSBlockCmt: - b.WriteByte(' ') - } - written = i1 - } - if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone { - // Preserve the portion between written and the comment start. - cs := i1 - 2 - if c1.state == stateHTMLCmt { - // "{{.C}}", - "Hello, <Cincinatti>", - }, - { - "HTML comment not first < in text node.", - "<!--", - "<!--", - }, - { - "HTML normalization 1", - "a < b", - "a < b", - }, - { - "HTML normalization 2", - "a << b", - "a << b", - }, - { - "HTML normalization 3", - "a<b", - "a<b", - }, - { - "HTML doctype not normalized", - "Hello, World!", - "Hello, World!", - }, - { - "No doctype injection", - `Hello, {{.C}}{{else}}world -->{{.W}}{{end}}", - "Hello, <Cincinatti>", - }, - { - "JS line comment", - "", - "", - }, - { - "JS multiline block comment", - "", - // Newline separates break from call. If newline - // removed, then break will consume label leaving - // code invalid. - "", - }, - { - "JS single-line block comment", - "", - // Newline separates break from call. If newline - // removed, then break will consume label leaving - // code invalid. - "", - }, - { - "JS block comment flush with mathematical division", - "", - "", - }, - { - "JS mixed comments", - "", - "", - }, - { - "CSS comments", - "`, - "", - }, - { - "JS attr block comment", - ``, - // Attribute comment tests should pass if the comments - // are successfully elided. - ``, - }, - { - "JS attr line comment", - ``, - ``, - }, - { - "CSS attr block comment", - ``, - ``, - }, - { - "CSS attr line comment", - ``, - ``, - }, - { - "HTML substitution commented out", - "

", - "

", - }, - { - "Comment ends flush with start", - "
", - "", - }, - { - "typed HTML in text", - `{{.W}}`, - `¡Hello, !`, - }, - { - "typed HTML in attribute", - `
`, - `
`, - }, - { - "typed HTML in script", - `