libgo: Update to weekly.2012-02-14 release.
From-SVN: r184798
This commit is contained in:
parent
ff2f581b00
commit
cbb6491d76
264 changed files with 11304 additions and 8940 deletions
|
@ -88,60 +88,6 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
|
|||
if (add_to_globals)
|
||||
this->add_named_object(no);
|
||||
|
||||
// Typeof.
|
||||
Type* empty_interface = Type::make_empty_interface_type(bloc);
|
||||
Typed_identifier_list* parameters = new Typed_identifier_list;
|
||||
parameters->push_back(Typed_identifier("i", empty_interface, bloc));
|
||||
results = new Typed_identifier_list;
|
||||
results->push_back(Typed_identifier("", empty_interface, bloc));
|
||||
fntype = Type::make_function_type(NULL, parameters, results, bloc);
|
||||
no = bindings->add_function_declaration("Typeof", package, fntype, bloc);
|
||||
if (add_to_globals)
|
||||
this->add_named_object(no);
|
||||
|
||||
// Reflect.
|
||||
parameters = new Typed_identifier_list;
|
||||
parameters->push_back(Typed_identifier("it", empty_interface, bloc));
|
||||
results = new Typed_identifier_list;
|
||||
results->push_back(Typed_identifier("", empty_interface, bloc));
|
||||
results->push_back(Typed_identifier("", pointer_type, bloc));
|
||||
fntype = Type::make_function_type(NULL, parameters, results, bloc);
|
||||
no = bindings->add_function_declaration("Reflect", package, fntype, bloc);
|
||||
if (add_to_globals)
|
||||
this->add_named_object(no);
|
||||
|
||||
// Unreflect.
|
||||
parameters = new Typed_identifier_list;
|
||||
parameters->push_back(Typed_identifier("typ", empty_interface, bloc));
|
||||
parameters->push_back(Typed_identifier("addr", pointer_type, bloc));
|
||||
results = new Typed_identifier_list;
|
||||
results->push_back(Typed_identifier("", empty_interface, bloc));
|
||||
fntype = Type::make_function_type(NULL, parameters, results, bloc);
|
||||
no = bindings->add_function_declaration("Unreflect", package, fntype, bloc);
|
||||
if (add_to_globals)
|
||||
this->add_named_object(no);
|
||||
|
||||
// New.
|
||||
parameters = new Typed_identifier_list;
|
||||
parameters->push_back(Typed_identifier("typ", empty_interface, bloc));
|
||||
results = new Typed_identifier_list;
|
||||
results->push_back(Typed_identifier("", pointer_type, bloc));
|
||||
fntype = Type::make_function_type(NULL, parameters, results, bloc);
|
||||
no = bindings->add_function_declaration("New", package, fntype, bloc);
|
||||
if (add_to_globals)
|
||||
this->add_named_object(no);
|
||||
|
||||
// NewArray.
|
||||
parameters = new Typed_identifier_list;
|
||||
parameters->push_back(Typed_identifier("typ", empty_interface, bloc));
|
||||
parameters->push_back(Typed_identifier("n", int_type, bloc));
|
||||
results = new Typed_identifier_list;
|
||||
results->push_back(Typed_identifier("", pointer_type, bloc));
|
||||
fntype = Type::make_function_type(NULL, parameters, results, bloc);
|
||||
no = bindings->add_function_declaration("NewArray", package, fntype, bloc);
|
||||
if (add_to_globals)
|
||||
this->add_named_object(no);
|
||||
|
||||
if (!this->imported_unsafe_)
|
||||
{
|
||||
go_imported_unsafe();
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
package main
|
||||
import "runtime"
|
||||
|
||||
func foo(runtime.UintType, i int) { // ERROR "cannot declare name runtime.UintType|named/anonymous mix"
|
||||
println(i, runtime.UintType)
|
||||
func foo(runtime.UintType, i int) { // ERROR "cannot declare name runtime.UintType|named/anonymous mix|undefined identifier"
|
||||
println(i, runtime.UintType) // GCCGO_ERROR "undefined identifier"
|
||||
}
|
||||
|
||||
func bar(i int) {
|
||||
runtime.UintType := i // ERROR "cannot declare name runtime.UintType|non-name on left side"
|
||||
println(runtime.UintType) // GCCGO_ERROR "invalid use of type"
|
||||
runtime.UintType := i // ERROR "cannot declare name runtime.UintType|non-name on left side|undefined identifier"
|
||||
println(runtime.UintType) // GCCGO_ERROR "invalid use of type|undefined identifier"
|
||||
}
|
||||
|
||||
func baz() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
52ba9506bd99
|
||||
43cf9b39b647
|
||||
|
||||
The first line of this file holds the Mercurial revision number of the
|
||||
last merge done from the master library sources.
|
||||
|
|
|
@ -225,7 +225,6 @@ toolexeclibgoexp_DATA = \
|
|||
$(exp_inotify_gox) \
|
||||
exp/norm.gox \
|
||||
exp/proxy.gox \
|
||||
exp/signal.gox \
|
||||
exp/terminal.gox \
|
||||
exp/types.gox \
|
||||
exp/utf8string.gox
|
||||
|
@ -325,6 +324,7 @@ toolexeclibgoosdir = $(toolexeclibgodir)/os
|
|||
|
||||
toolexeclibgoos_DATA = \
|
||||
os/exec.gox \
|
||||
os/signal.gox \
|
||||
os/user.gox
|
||||
|
||||
toolexeclibgopathdir = $(toolexeclibgodir)/path
|
||||
|
@ -352,8 +352,7 @@ toolexeclibgotestingdir = $(toolexeclibgodir)/testing
|
|||
|
||||
toolexeclibgotesting_DATA = \
|
||||
testing/iotest.gox \
|
||||
testing/quick.gox \
|
||||
testing/script.gox
|
||||
testing/quick.gox
|
||||
|
||||
toolexeclibgotextdir = $(toolexeclibgodir)/text
|
||||
|
||||
|
@ -398,6 +397,7 @@ runtime_files = \
|
|||
runtime/go-byte-array-to-string.c \
|
||||
runtime/go-breakpoint.c \
|
||||
runtime/go-caller.c \
|
||||
runtime/go-callers.c \
|
||||
runtime/go-can-convert-interface.c \
|
||||
runtime/go-cgo.c \
|
||||
runtime/go-check-interface.c \
|
||||
|
@ -428,7 +428,6 @@ runtime_files = \
|
|||
runtime/go-panic.c \
|
||||
runtime/go-print.c \
|
||||
runtime/go-recover.c \
|
||||
runtime/go-reflect.c \
|
||||
runtime/go-reflect-call.c \
|
||||
runtime/go-reflect-map.c \
|
||||
runtime/go-rune.c \
|
||||
|
@ -450,7 +449,6 @@ runtime_files = \
|
|||
runtime/go-type-string.c \
|
||||
runtime/go-typedesc-equal.c \
|
||||
runtime/go-typestring.c \
|
||||
runtime/go-unreflect.c \
|
||||
runtime/go-unsafe-new.c \
|
||||
runtime/go-unsafe-newarray.c \
|
||||
runtime/go-unsafe-pointer.c \
|
||||
|
@ -468,6 +466,7 @@ runtime_files = \
|
|||
runtime/msize.c \
|
||||
runtime/proc.c \
|
||||
runtime/runtime.c \
|
||||
runtime/signal_unix.c \
|
||||
runtime/thread.c \
|
||||
runtime/yield.c \
|
||||
$(rtems_task_variable_add_file) \
|
||||
|
@ -509,7 +508,7 @@ sema.c: $(srcdir)/runtime/sema.goc goc2c
|
|||
mv -f $@.tmp $@
|
||||
|
||||
sigqueue.c: $(srcdir)/runtime/sigqueue.goc goc2c
|
||||
./goc2c --gcc --go-prefix libgo_runtime $< > $@.tmp
|
||||
./goc2c --gcc --go-prefix libgo_os $< > $@.tmp
|
||||
mv -f $@.tmp $@
|
||||
|
||||
time.c: $(srcdir)/runtime/time.goc goc2c
|
||||
|
@ -526,7 +525,8 @@ go_bufio_files = \
|
|||
go_bytes_files = \
|
||||
go/bytes/buffer.go \
|
||||
go/bytes/bytes.go \
|
||||
go/bytes/bytes_decl.go
|
||||
go/bytes/bytes_decl.go \
|
||||
go/bytes/reader.go
|
||||
go_bytes_c_files = \
|
||||
go/bytes/indexbyte.c
|
||||
|
||||
|
@ -784,9 +784,7 @@ go_os_files = \
|
|||
$(go_os_stat_file) \
|
||||
go/os/str.go \
|
||||
$(go_os_sys_file) \
|
||||
go/os/time.go \
|
||||
go/os/types.go \
|
||||
signal_unix.go
|
||||
go/os/types.go
|
||||
|
||||
go_path_files = \
|
||||
go/path/match.go \
|
||||
|
@ -811,7 +809,6 @@ go_runtime_files = \
|
|||
go/runtime/error.go \
|
||||
go/runtime/extern.go \
|
||||
go/runtime/mem.go \
|
||||
go/runtime/sig.go \
|
||||
go/runtime/softfloat64.go \
|
||||
go/runtime/type.go \
|
||||
version.go
|
||||
|
@ -1103,8 +1100,6 @@ go_exp_proxy_files = \
|
|||
go/exp/proxy/per_host.go \
|
||||
go/exp/proxy/proxy.go \
|
||||
go/exp/proxy/socks5.go
|
||||
go_exp_signal_files = \
|
||||
go/exp/signal/signal.go
|
||||
go_exp_terminal_files = \
|
||||
go/exp/terminal/terminal.go \
|
||||
go/exp/terminal/util.go
|
||||
|
@ -1302,6 +1297,10 @@ go_os_exec_files = \
|
|||
go/os/exec/exec.go \
|
||||
go/os/exec/lp_unix.go
|
||||
|
||||
go_os_signal_files = \
|
||||
go/os/signal/signal.go \
|
||||
go/os/signal/signal_unix.go
|
||||
|
||||
go_os_user_files = \
|
||||
go/os/user/user.go \
|
||||
go/os/user/lookup_unix.go
|
||||
|
@ -1352,8 +1351,6 @@ go_testing_iotest_files = \
|
|||
go/testing/iotest/writer.go
|
||||
go_testing_quick_files = \
|
||||
go/testing/quick/quick.go
|
||||
go_testing_script_files = \
|
||||
go/testing/script/script.go
|
||||
|
||||
go_text_scanner_files = \
|
||||
go/text/scanner/scanner.go
|
||||
|
@ -1529,6 +1526,7 @@ go_syscall_files = \
|
|||
syscall_arch.go
|
||||
go_syscall_c_files = \
|
||||
go/syscall/errno.c \
|
||||
go/syscall/signame.c \
|
||||
$(syscall_wait_c_file)
|
||||
|
||||
libcalls.go: s-libcalls; @true
|
||||
|
@ -1667,7 +1665,6 @@ libgo_go_objs = \
|
|||
exp/html.lo \
|
||||
exp/norm.lo \
|
||||
exp/proxy.lo \
|
||||
exp/signal.lo \
|
||||
exp/terminal.lo \
|
||||
exp/types.lo \
|
||||
exp/utf8string.lo \
|
||||
|
@ -1712,6 +1709,7 @@ libgo_go_objs = \
|
|||
old/regexp.lo \
|
||||
old/template.lo \
|
||||
$(os_lib_inotify_lo) \
|
||||
os/signal.lo \
|
||||
os/user.lo \
|
||||
path/filepath.lo \
|
||||
regexp/syntax.lo \
|
||||
|
@ -1722,6 +1720,7 @@ libgo_go_objs = \
|
|||
sync/atomic_c.lo \
|
||||
syscall/syscall.lo \
|
||||
syscall/errno.lo \
|
||||
syscall/signame.lo \
|
||||
syscall/wait.lo \
|
||||
text/scanner.lo \
|
||||
text/tabwriter.lo \
|
||||
|
@ -1730,7 +1729,6 @@ libgo_go_objs = \
|
|||
testing/testing.lo \
|
||||
testing/iotest.lo \
|
||||
testing/quick.lo \
|
||||
testing/script.lo \
|
||||
unicode/utf16.lo \
|
||||
unicode/utf8.lo
|
||||
|
||||
|
@ -1986,10 +1984,6 @@ os/check: $(CHECK_DEPS)
|
|||
@$(CHECK)
|
||||
.PHONY: os/check
|
||||
|
||||
signal_unix.go: $(srcdir)/go/os/mkunixsignals.sh sysinfo.go
|
||||
$(SHELL) $(srcdir)/go/os/mkunixsignals.sh sysinfo.go > $@.tmp
|
||||
mv -f $@.tmp $@
|
||||
|
||||
@go_include@ path/path.lo.dep
|
||||
path/path.lo.dep: $(go_path_files)
|
||||
$(BUILDDEPS)
|
||||
|
@ -2599,16 +2593,6 @@ exp/proxy/check: $(CHECK_DEPS)
|
|||
@$(CHECK)
|
||||
.PHONY: exp/proxy/check
|
||||
|
||||
@go_include@ exp/signal.lo.dep
|
||||
exp/signal.lo.dep: $(go_exp_signal_files)
|
||||
$(BUILDDEPS)
|
||||
exp/signal.lo: $(go_exp_signal_files)
|
||||
$(BUILDPACKAGE)
|
||||
exp/signal/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) exp/signal
|
||||
@$(CHECK)
|
||||
.PHONY: exp/signal/check
|
||||
|
||||
@go_include@ exp/terminal.lo.dep
|
||||
exp/terminal.lo.dep: $(go_exp_terminal_files)
|
||||
$(BUILDDEPS)
|
||||
|
@ -3060,6 +3044,16 @@ os/exec/check: $(CHECK_DEPS)
|
|||
@$(CHECK)
|
||||
.PHONY: os/exec/check
|
||||
|
||||
@go_include@ os/signal.lo.dep
|
||||
os/signal.lo.dep: $(go_os_signal_files)
|
||||
$(BUILDDEPS)
|
||||
os/signal.lo: $(go_os_signal_files)
|
||||
$(BUILDPACKAGE)
|
||||
os/signal/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) os/signal
|
||||
@$(CHECK)
|
||||
.PHONY: os/signal/check
|
||||
|
||||
@go_include@ os/user.lo.dep
|
||||
os/user.lo.dep: $(go_os_user_files)
|
||||
$(BUILDDEPS)
|
||||
|
@ -3171,16 +3165,6 @@ testing/quick/check: $(CHECK_DEPS)
|
|||
@$(CHECK)
|
||||
.PHONY: testing/quick/check
|
||||
|
||||
@go_include@ testing/script.lo.dep
|
||||
testing/script.lo.dep: $(go_testing_script_files)
|
||||
$(BUILDDEPS)
|
||||
testing/script.lo: $(go_testing_script_files)
|
||||
$(BUILDPACKAGE)
|
||||
testing/script/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) testing/script
|
||||
@$(CHECK)
|
||||
.PHONY: testing/script/check
|
||||
|
||||
@go_include@ unicode/utf16.lo.dep
|
||||
unicode/utf16.lo.dep: $(go_unicode_utf16_files)
|
||||
$(BUILDDEPS)
|
||||
|
@ -3208,6 +3192,8 @@ syscall/syscall.lo: $(go_syscall_files)
|
|||
$(BUILDPACKAGE)
|
||||
syscall/errno.lo: go/syscall/errno.c
|
||||
$(LTCOMPILE) -c -o $@ $<
|
||||
syscall/signame.lo: go/syscall/signame.c
|
||||
$(LTCOMPILE) -c -o $@ $<
|
||||
syscall/wait.lo: go/syscall/wait.c
|
||||
$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
|
@ -3384,8 +3370,6 @@ exp/norm.gox: exp/norm.lo
|
|||
$(BUILDGOX)
|
||||
exp/proxy.gox: exp/proxy.lo
|
||||
$(BUILDGOX)
|
||||
exp/signal.gox: exp/signal.lo
|
||||
$(BUILDGOX)
|
||||
exp/terminal.gox: exp/terminal.lo
|
||||
$(BUILDGOX)
|
||||
exp/types.gox: exp/types.lo
|
||||
|
@ -3486,6 +3470,8 @@ old/template.gox: old/template.lo
|
|||
|
||||
os/exec.gox: os/exec.lo
|
||||
$(BUILDGOX)
|
||||
os/signal.gox: os/signal.lo
|
||||
$(BUILDGOX)
|
||||
os/user.gox: os/user.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
|
@ -3516,8 +3502,6 @@ testing/iotest.gox: testing/iotest.lo
|
|||
$(BUILDGOX)
|
||||
testing/quick.gox: testing/quick.lo
|
||||
$(BUILDGOX)
|
||||
testing/script.gox: testing/script.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
unicode/utf16.gox: unicode/utf16.lo
|
||||
$(BUILDGOX)
|
||||
|
@ -3605,7 +3589,6 @@ TEST_PACKAGES = \
|
|||
$(exp_inotify_check) \
|
||||
exp/norm/check \
|
||||
exp/proxy/check \
|
||||
exp/signal/check \
|
||||
exp/terminal/check \
|
||||
exp/utf8string/check \
|
||||
html/template/check \
|
||||
|
@ -3635,6 +3618,7 @@ TEST_PACKAGES = \
|
|||
net/http/check \
|
||||
net/http/cgi/check \
|
||||
net/http/fcgi/check \
|
||||
net/http/httptest/check \
|
||||
net/http/httputil/check \
|
||||
net/mail/check \
|
||||
net/rpc/check \
|
||||
|
@ -3646,6 +3630,7 @@ TEST_PACKAGES = \
|
|||
old/regexp/check \
|
||||
old/template/check \
|
||||
os/exec/check \
|
||||
os/signal/check \
|
||||
os/user/check \
|
||||
path/filepath/check \
|
||||
regexp/syntax/check \
|
||||
|
@ -3655,7 +3640,6 @@ TEST_PACKAGES = \
|
|||
text/template/check \
|
||||
text/template/parse/check \
|
||||
testing/quick/check \
|
||||
testing/script/check \
|
||||
unicode/utf16/check \
|
||||
unicode/utf8/check
|
||||
|
||||
|
|
|
@ -154,25 +154,25 @@ am__DEPENDENCIES_2 = bufio/bufio.lo bytes/bytes.lo bytes/index.lo \
|
|||
encoding/base32.lo encoding/base64.lo encoding/binary.lo \
|
||||
encoding/csv.lo encoding/gob.lo encoding/hex.lo \
|
||||
encoding/json.lo encoding/pem.lo encoding/xml.lo exp/ebnf.lo \
|
||||
exp/html.lo exp/norm.lo exp/proxy.lo exp/signal.lo \
|
||||
exp/terminal.lo exp/types.lo exp/utf8string.lo \
|
||||
html/template.lo go/ast.lo go/build.lo go/doc.lo go/parser.lo \
|
||||
go/printer.lo go/scanner.lo go/token.lo hash/adler32.lo \
|
||||
hash/crc32.lo hash/crc64.lo hash/fnv.lo net/http/cgi.lo \
|
||||
net/http/fcgi.lo net/http/httptest.lo net/http/httputil.lo \
|
||||
net/http/pprof.lo image/color.lo image/draw.lo image/gif.lo \
|
||||
image/jpeg.lo image/png.lo index/suffixarray.lo io/ioutil.lo \
|
||||
log/syslog.lo log/syslog/syslog_c.lo math/big.lo math/cmplx.lo \
|
||||
math/rand.lo mime/mime.lo mime/multipart.lo net/http.lo \
|
||||
net/mail.lo net/rpc.lo net/smtp.lo net/textproto.lo net/url.lo \
|
||||
exp/html.lo exp/norm.lo exp/proxy.lo exp/terminal.lo \
|
||||
exp/types.lo exp/utf8string.lo html/template.lo go/ast.lo \
|
||||
go/build.lo go/doc.lo go/parser.lo go/printer.lo go/scanner.lo \
|
||||
go/token.lo hash/adler32.lo hash/crc32.lo hash/crc64.lo \
|
||||
hash/fnv.lo net/http/cgi.lo net/http/fcgi.lo \
|
||||
net/http/httptest.lo net/http/httputil.lo net/http/pprof.lo \
|
||||
image/color.lo image/draw.lo image/gif.lo image/jpeg.lo \
|
||||
image/png.lo index/suffixarray.lo io/ioutil.lo log/syslog.lo \
|
||||
log/syslog/syslog_c.lo math/big.lo math/cmplx.lo math/rand.lo \
|
||||
mime/mime.lo mime/multipart.lo net/http.lo net/mail.lo \
|
||||
net/rpc.lo net/smtp.lo net/textproto.lo net/url.lo \
|
||||
old/netchan.lo old/regexp.lo old/template.lo \
|
||||
$(am__DEPENDENCIES_1) os/user.lo path/filepath.lo \
|
||||
$(am__DEPENDENCIES_1) os/signal.lo os/user.lo path/filepath.lo \
|
||||
regexp/syntax.lo net/rpc/jsonrpc.lo runtime/debug.lo \
|
||||
runtime/pprof.lo sync/atomic.lo sync/atomic_c.lo \
|
||||
syscall/syscall.lo syscall/errno.lo syscall/wait.lo \
|
||||
text/scanner.lo text/tabwriter.lo text/template.lo \
|
||||
text/template/parse.lo testing/testing.lo testing/iotest.lo \
|
||||
testing/quick.lo testing/script.lo unicode/utf16.lo \
|
||||
syscall/syscall.lo syscall/errno.lo syscall/signame.lo \
|
||||
syscall/wait.lo text/scanner.lo text/tabwriter.lo \
|
||||
text/template.lo text/template/parse.lo testing/testing.lo \
|
||||
testing/iotest.lo testing/quick.lo unicode/utf16.lo \
|
||||
unicode/utf8.lo
|
||||
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
|
||||
|
@ -180,14 +180,14 @@ libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
|||
am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
|
||||
runtime/go-assert-interface.c \
|
||||
runtime/go-byte-array-to-string.c runtime/go-breakpoint.c \
|
||||
runtime/go-caller.c runtime/go-can-convert-interface.c \
|
||||
runtime/go-cgo.c runtime/go-check-interface.c \
|
||||
runtime/go-construct-map.c runtime/go-convert-interface.c \
|
||||
runtime/go-copy.c runtime/go-defer.c \
|
||||
runtime/go-deferred-recover.c runtime/go-eface-compare.c \
|
||||
runtime/go-eface-val-compare.c runtime/go-getgoroot.c \
|
||||
runtime/go-int-array-to-string.c runtime/go-int-to-string.c \
|
||||
runtime/go-interface-compare.c \
|
||||
runtime/go-caller.c runtime/go-callers.c \
|
||||
runtime/go-can-convert-interface.c runtime/go-cgo.c \
|
||||
runtime/go-check-interface.c runtime/go-construct-map.c \
|
||||
runtime/go-convert-interface.c runtime/go-copy.c \
|
||||
runtime/go-defer.c runtime/go-deferred-recover.c \
|
||||
runtime/go-eface-compare.c runtime/go-eface-val-compare.c \
|
||||
runtime/go-getgoroot.c runtime/go-int-array-to-string.c \
|
||||
runtime/go-int-to-string.c runtime/go-interface-compare.c \
|
||||
runtime/go-interface-eface-compare.c \
|
||||
runtime/go-interface-val-compare.c runtime/go-make-slice.c \
|
||||
runtime/go-map-delete.c runtime/go-map-index.c \
|
||||
|
@ -195,10 +195,9 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
|
|||
runtime/go-matherr.c runtime/go-nanotime.c runtime/go-now.c \
|
||||
runtime/go-new-map.c runtime/go-new.c runtime/go-nosys.c \
|
||||
runtime/go-panic.c runtime/go-print.c runtime/go-recover.c \
|
||||
runtime/go-reflect.c runtime/go-reflect-call.c \
|
||||
runtime/go-reflect-map.c runtime/go-rune.c \
|
||||
runtime/go-runtime-error.c runtime/go-setenv.c \
|
||||
runtime/go-signal.c runtime/go-strcmp.c \
|
||||
runtime/go-reflect-call.c runtime/go-reflect-map.c \
|
||||
runtime/go-rune.c runtime/go-runtime-error.c \
|
||||
runtime/go-setenv.c runtime/go-signal.c runtime/go-strcmp.c \
|
||||
runtime/go-string-to-byte-array.c \
|
||||
runtime/go-string-to-int-array.c runtime/go-strplus.c \
|
||||
runtime/go-strslice.c runtime/go-trampoline.c \
|
||||
|
@ -206,15 +205,15 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
|
|||
runtime/go-type-error.c runtime/go-type-float.c \
|
||||
runtime/go-type-identity.c runtime/go-type-interface.c \
|
||||
runtime/go-type-string.c runtime/go-typedesc-equal.c \
|
||||
runtime/go-typestring.c runtime/go-unreflect.c \
|
||||
runtime/go-unsafe-new.c runtime/go-unsafe-newarray.c \
|
||||
runtime/go-unsafe-pointer.c runtime/go-unwind.c runtime/chan.c \
|
||||
runtime/cpuprof.c runtime/lock_sema.c runtime/thread-sema.c \
|
||||
runtime/lock_futex.c runtime/thread-linux.c runtime/mcache.c \
|
||||
runtime/mcentral.c runtime/mem_posix_memalign.c runtime/mem.c \
|
||||
runtime/mfinal.c runtime/mfixalloc.c runtime/mgc0.c \
|
||||
runtime/mheap.c runtime/msize.c runtime/proc.c \
|
||||
runtime/runtime.c runtime/thread.c runtime/yield.c \
|
||||
runtime/go-typestring.c runtime/go-unsafe-new.c \
|
||||
runtime/go-unsafe-newarray.c runtime/go-unsafe-pointer.c \
|
||||
runtime/go-unwind.c runtime/chan.c runtime/cpuprof.c \
|
||||
runtime/lock_sema.c runtime/thread-sema.c runtime/lock_futex.c \
|
||||
runtime/thread-linux.c runtime/mcache.c runtime/mcentral.c \
|
||||
runtime/mem_posix_memalign.c runtime/mem.c runtime/mfinal.c \
|
||||
runtime/mfixalloc.c runtime/mgc0.c runtime/mheap.c \
|
||||
runtime/msize.c runtime/proc.c runtime/runtime.c \
|
||||
runtime/signal_unix.c runtime/thread.c runtime/yield.c \
|
||||
runtime/rtems-task-variable-add.c iface.c malloc.c map.c \
|
||||
mprof.c reflect.c runtime1.c sema.c sigqueue.c string.c time.c
|
||||
@LIBGO_IS_LINUX_FALSE@am__objects_1 = lock_sema.lo thread-sema.lo
|
||||
|
@ -224,30 +223,30 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
|
|||
@LIBGO_IS_RTEMS_TRUE@am__objects_3 = rtems-task-variable-add.lo
|
||||
am__objects_4 = go-append.lo go-assert.lo go-assert-interface.lo \
|
||||
go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \
|
||||
go-can-convert-interface.lo go-cgo.lo go-check-interface.lo \
|
||||
go-construct-map.lo go-convert-interface.lo go-copy.lo \
|
||||
go-defer.lo go-deferred-recover.lo go-eface-compare.lo \
|
||||
go-callers.lo go-can-convert-interface.lo go-cgo.lo \
|
||||
go-check-interface.lo go-construct-map.lo \
|
||||
go-convert-interface.lo go-copy.lo go-defer.lo \
|
||||
go-deferred-recover.lo go-eface-compare.lo \
|
||||
go-eface-val-compare.lo go-getgoroot.lo \
|
||||
go-int-array-to-string.lo go-int-to-string.lo \
|
||||
go-interface-compare.lo go-interface-eface-compare.lo \
|
||||
go-interface-val-compare.lo go-make-slice.lo go-map-delete.lo \
|
||||
go-map-index.lo go-map-len.lo go-map-range.lo go-matherr.lo \
|
||||
go-nanotime.lo go-now.lo go-new-map.lo go-new.lo go-nosys.lo \
|
||||
go-panic.lo go-print.lo go-recover.lo go-reflect.lo \
|
||||
go-reflect-call.lo go-reflect-map.lo go-rune.lo \
|
||||
go-runtime-error.lo go-setenv.lo go-signal.lo go-strcmp.lo \
|
||||
go-string-to-byte-array.lo go-string-to-int-array.lo \
|
||||
go-strplus.lo go-strslice.lo go-trampoline.lo \
|
||||
go-type-complex.lo go-type-eface.lo go-type-error.lo \
|
||||
go-type-float.lo go-type-identity.lo go-type-interface.lo \
|
||||
go-type-string.lo go-typedesc-equal.lo go-typestring.lo \
|
||||
go-unreflect.lo go-unsafe-new.lo go-unsafe-newarray.lo \
|
||||
go-panic.lo go-print.lo go-recover.lo go-reflect-call.lo \
|
||||
go-reflect-map.lo go-rune.lo go-runtime-error.lo go-setenv.lo \
|
||||
go-signal.lo go-strcmp.lo go-string-to-byte-array.lo \
|
||||
go-string-to-int-array.lo go-strplus.lo go-strslice.lo \
|
||||
go-trampoline.lo go-type-complex.lo go-type-eface.lo \
|
||||
go-type-error.lo go-type-float.lo go-type-identity.lo \
|
||||
go-type-interface.lo go-type-string.lo go-typedesc-equal.lo \
|
||||
go-typestring.lo go-unsafe-new.lo go-unsafe-newarray.lo \
|
||||
go-unsafe-pointer.lo go-unwind.lo chan.lo cpuprof.lo \
|
||||
$(am__objects_1) mcache.lo mcentral.lo $(am__objects_2) \
|
||||
mfinal.lo mfixalloc.lo mgc0.lo mheap.lo msize.lo proc.lo \
|
||||
runtime.lo thread.lo yield.lo $(am__objects_3) iface.lo \
|
||||
malloc.lo map.lo mprof.lo reflect.lo runtime1.lo sema.lo \
|
||||
sigqueue.lo string.lo time.lo
|
||||
runtime.lo signal_unix.lo thread.lo yield.lo $(am__objects_3) \
|
||||
iface.lo malloc.lo map.lo mprof.lo reflect.lo runtime1.lo \
|
||||
sema.lo sigqueue.lo string.lo time.lo
|
||||
am_libgo_la_OBJECTS = $(am__objects_4)
|
||||
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
|
||||
libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
|
@ -679,7 +678,6 @@ toolexeclibgoexp_DATA = \
|
|||
$(exp_inotify_gox) \
|
||||
exp/norm.gox \
|
||||
exp/proxy.gox \
|
||||
exp/signal.gox \
|
||||
exp/terminal.gox \
|
||||
exp/types.gox \
|
||||
exp/utf8string.gox
|
||||
|
@ -765,6 +763,7 @@ toolexeclibgoold_DATA = \
|
|||
toolexeclibgoosdir = $(toolexeclibgodir)/os
|
||||
toolexeclibgoos_DATA = \
|
||||
os/exec.gox \
|
||||
os/signal.gox \
|
||||
os/user.gox
|
||||
|
||||
toolexeclibgopathdir = $(toolexeclibgodir)/path
|
||||
|
@ -787,8 +786,7 @@ toolexeclibgosync_DATA = \
|
|||
toolexeclibgotestingdir = $(toolexeclibgodir)/testing
|
||||
toolexeclibgotesting_DATA = \
|
||||
testing/iotest.gox \
|
||||
testing/quick.gox \
|
||||
testing/script.gox
|
||||
testing/quick.gox
|
||||
|
||||
toolexeclibgotextdir = $(toolexeclibgodir)/text
|
||||
toolexeclibgotext_DATA = \
|
||||
|
@ -818,6 +816,7 @@ runtime_files = \
|
|||
runtime/go-byte-array-to-string.c \
|
||||
runtime/go-breakpoint.c \
|
||||
runtime/go-caller.c \
|
||||
runtime/go-callers.c \
|
||||
runtime/go-can-convert-interface.c \
|
||||
runtime/go-cgo.c \
|
||||
runtime/go-check-interface.c \
|
||||
|
@ -848,7 +847,6 @@ runtime_files = \
|
|||
runtime/go-panic.c \
|
||||
runtime/go-print.c \
|
||||
runtime/go-recover.c \
|
||||
runtime/go-reflect.c \
|
||||
runtime/go-reflect-call.c \
|
||||
runtime/go-reflect-map.c \
|
||||
runtime/go-rune.c \
|
||||
|
@ -870,7 +868,6 @@ runtime_files = \
|
|||
runtime/go-type-string.c \
|
||||
runtime/go-typedesc-equal.c \
|
||||
runtime/go-typestring.c \
|
||||
runtime/go-unreflect.c \
|
||||
runtime/go-unsafe-new.c \
|
||||
runtime/go-unsafe-newarray.c \
|
||||
runtime/go-unsafe-pointer.c \
|
||||
|
@ -888,6 +885,7 @@ runtime_files = \
|
|||
runtime/msize.c \
|
||||
runtime/proc.c \
|
||||
runtime/runtime.c \
|
||||
runtime/signal_unix.c \
|
||||
runtime/thread.c \
|
||||
runtime/yield.c \
|
||||
$(rtems_task_variable_add_file) \
|
||||
|
@ -908,7 +906,8 @@ go_bufio_files = \
|
|||
go_bytes_files = \
|
||||
go/bytes/buffer.go \
|
||||
go/bytes/bytes.go \
|
||||
go/bytes/bytes_decl.go
|
||||
go/bytes/bytes_decl.go \
|
||||
go/bytes/reader.go
|
||||
|
||||
go_bytes_c_files = \
|
||||
go/bytes/indexbyte.c
|
||||
|
@ -1106,9 +1105,7 @@ go_os_files = \
|
|||
$(go_os_stat_file) \
|
||||
go/os/str.go \
|
||||
$(go_os_sys_file) \
|
||||
go/os/time.go \
|
||||
go/os/types.go \
|
||||
signal_unix.go
|
||||
go/os/types.go
|
||||
|
||||
go_path_files = \
|
||||
go/path/match.go \
|
||||
|
@ -1133,7 +1130,6 @@ go_runtime_files = \
|
|||
go/runtime/error.go \
|
||||
go/runtime/extern.go \
|
||||
go/runtime/mem.go \
|
||||
go/runtime/sig.go \
|
||||
go/runtime/softfloat64.go \
|
||||
go/runtime/type.go \
|
||||
version.go
|
||||
|
@ -1442,9 +1438,6 @@ go_exp_proxy_files = \
|
|||
go/exp/proxy/proxy.go \
|
||||
go/exp/proxy/socks5.go
|
||||
|
||||
go_exp_signal_files = \
|
||||
go/exp/signal/signal.go
|
||||
|
||||
go_exp_terminal_files = \
|
||||
go/exp/terminal/terminal.go \
|
||||
go/exp/terminal/util.go
|
||||
|
@ -1664,6 +1657,10 @@ go_os_exec_files = \
|
|||
go/os/exec/exec.go \
|
||||
go/os/exec/lp_unix.go
|
||||
|
||||
go_os_signal_files = \
|
||||
go/os/signal/signal.go \
|
||||
go/os/signal/signal_unix.go
|
||||
|
||||
go_os_user_files = \
|
||||
go/os/user/user.go \
|
||||
go/os/user/lookup_unix.go
|
||||
|
@ -1720,9 +1717,6 @@ go_testing_iotest_files = \
|
|||
go_testing_quick_files = \
|
||||
go/testing/quick/quick.go
|
||||
|
||||
go_testing_script_files = \
|
||||
go/testing/script/script.go
|
||||
|
||||
go_text_scanner_files = \
|
||||
go/text/scanner/scanner.go
|
||||
|
||||
|
@ -1833,6 +1827,7 @@ go_syscall_files = \
|
|||
|
||||
go_syscall_c_files = \
|
||||
go/syscall/errno.c \
|
||||
go/syscall/signame.c \
|
||||
$(syscall_wait_c_file)
|
||||
|
||||
@LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo =
|
||||
|
@ -1917,7 +1912,6 @@ libgo_go_objs = \
|
|||
exp/html.lo \
|
||||
exp/norm.lo \
|
||||
exp/proxy.lo \
|
||||
exp/signal.lo \
|
||||
exp/terminal.lo \
|
||||
exp/types.lo \
|
||||
exp/utf8string.lo \
|
||||
|
@ -1962,6 +1956,7 @@ libgo_go_objs = \
|
|||
old/regexp.lo \
|
||||
old/template.lo \
|
||||
$(os_lib_inotify_lo) \
|
||||
os/signal.lo \
|
||||
os/user.lo \
|
||||
path/filepath.lo \
|
||||
regexp/syntax.lo \
|
||||
|
@ -1972,6 +1967,7 @@ libgo_go_objs = \
|
|||
sync/atomic_c.lo \
|
||||
syscall/syscall.lo \
|
||||
syscall/errno.lo \
|
||||
syscall/signame.lo \
|
||||
syscall/wait.lo \
|
||||
text/scanner.lo \
|
||||
text/tabwriter.lo \
|
||||
|
@ -1980,7 +1976,6 @@ libgo_go_objs = \
|
|||
testing/testing.lo \
|
||||
testing/iotest.lo \
|
||||
testing/quick.lo \
|
||||
testing/script.lo \
|
||||
unicode/utf16.lo \
|
||||
unicode/utf8.lo
|
||||
|
||||
|
@ -2166,7 +2161,6 @@ TEST_PACKAGES = \
|
|||
$(exp_inotify_check) \
|
||||
exp/norm/check \
|
||||
exp/proxy/check \
|
||||
exp/signal/check \
|
||||
exp/terminal/check \
|
||||
exp/utf8string/check \
|
||||
html/template/check \
|
||||
|
@ -2196,6 +2190,7 @@ TEST_PACKAGES = \
|
|||
net/http/check \
|
||||
net/http/cgi/check \
|
||||
net/http/fcgi/check \
|
||||
net/http/httptest/check \
|
||||
net/http/httputil/check \
|
||||
net/mail/check \
|
||||
net/rpc/check \
|
||||
|
@ -2207,6 +2202,7 @@ TEST_PACKAGES = \
|
|||
old/regexp/check \
|
||||
old/template/check \
|
||||
os/exec/check \
|
||||
os/signal/check \
|
||||
os/user/check \
|
||||
path/filepath/check \
|
||||
regexp/syntax/check \
|
||||
|
@ -2216,7 +2212,6 @@ TEST_PACKAGES = \
|
|||
text/template/check \
|
||||
text/template/parse/check \
|
||||
testing/quick/check \
|
||||
testing/script/check \
|
||||
unicode/utf16/check \
|
||||
unicode/utf8/check
|
||||
|
||||
|
@ -2362,6 +2357,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-breakpoint.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-byte-array-to-string.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-caller.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-callers.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-can-convert-interface.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cgo.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-check-interface.Plo@am__quote@
|
||||
|
@ -2395,7 +2391,6 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-recover.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-call.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-map.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rune.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-runtime-error.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-setenv.Plo@am__quote@
|
||||
|
@ -2415,7 +2410,6 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-string.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-typedesc-equal.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-typestring.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unreflect.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-new.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-newarray.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-pointer.Plo@am__quote@
|
||||
|
@ -2441,6 +2435,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime1.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sema.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signal_unix.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigqueue.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread-linux.Plo@am__quote@
|
||||
|
@ -2526,6 +2521,13 @@ go-caller.lo: runtime/go-caller.c
|
|||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-caller.lo `test -f 'runtime/go-caller.c' || echo '$(srcdir)/'`runtime/go-caller.c
|
||||
|
||||
go-callers.lo: runtime/go-callers.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-callers.lo -MD -MP -MF $(DEPDIR)/go-callers.Tpo -c -o go-callers.lo `test -f 'runtime/go-callers.c' || echo '$(srcdir)/'`runtime/go-callers.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-callers.Tpo $(DEPDIR)/go-callers.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-callers.c' object='go-callers.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-callers.lo `test -f 'runtime/go-callers.c' || echo '$(srcdir)/'`runtime/go-callers.c
|
||||
|
||||
go-can-convert-interface.lo: runtime/go-can-convert-interface.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-can-convert-interface.lo -MD -MP -MF $(DEPDIR)/go-can-convert-interface.Tpo -c -o go-can-convert-interface.lo `test -f 'runtime/go-can-convert-interface.c' || echo '$(srcdir)/'`runtime/go-can-convert-interface.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-can-convert-interface.Tpo $(DEPDIR)/go-can-convert-interface.Plo
|
||||
|
@ -2736,13 +2738,6 @@ go-recover.lo: runtime/go-recover.c
|
|||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-recover.lo `test -f 'runtime/go-recover.c' || echo '$(srcdir)/'`runtime/go-recover.c
|
||||
|
||||
go-reflect.lo: runtime/go-reflect.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-reflect.lo -MD -MP -MF $(DEPDIR)/go-reflect.Tpo -c -o go-reflect.lo `test -f 'runtime/go-reflect.c' || echo '$(srcdir)/'`runtime/go-reflect.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-reflect.Tpo $(DEPDIR)/go-reflect.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-reflect.c' object='go-reflect.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-reflect.lo `test -f 'runtime/go-reflect.c' || echo '$(srcdir)/'`runtime/go-reflect.c
|
||||
|
||||
go-reflect-call.lo: runtime/go-reflect-call.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-reflect-call.lo -MD -MP -MF $(DEPDIR)/go-reflect-call.Tpo -c -o go-reflect-call.lo `test -f 'runtime/go-reflect-call.c' || echo '$(srcdir)/'`runtime/go-reflect-call.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-reflect-call.Tpo $(DEPDIR)/go-reflect-call.Plo
|
||||
|
@ -2890,13 +2885,6 @@ go-typestring.lo: runtime/go-typestring.c
|
|||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-typestring.lo `test -f 'runtime/go-typestring.c' || echo '$(srcdir)/'`runtime/go-typestring.c
|
||||
|
||||
go-unreflect.lo: runtime/go-unreflect.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-unreflect.lo -MD -MP -MF $(DEPDIR)/go-unreflect.Tpo -c -o go-unreflect.lo `test -f 'runtime/go-unreflect.c' || echo '$(srcdir)/'`runtime/go-unreflect.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-unreflect.Tpo $(DEPDIR)/go-unreflect.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-unreflect.c' object='go-unreflect.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-unreflect.lo `test -f 'runtime/go-unreflect.c' || echo '$(srcdir)/'`runtime/go-unreflect.c
|
||||
|
||||
go-unsafe-new.lo: runtime/go-unsafe-new.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-unsafe-new.lo -MD -MP -MF $(DEPDIR)/go-unsafe-new.Tpo -c -o go-unsafe-new.lo `test -f 'runtime/go-unsafe-new.c' || echo '$(srcdir)/'`runtime/go-unsafe-new.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-unsafe-new.Tpo $(DEPDIR)/go-unsafe-new.Plo
|
||||
|
@ -3044,6 +3032,13 @@ runtime.lo: runtime/runtime.c
|
|||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o runtime.lo `test -f 'runtime/runtime.c' || echo '$(srcdir)/'`runtime/runtime.c
|
||||
|
||||
signal_unix.lo: runtime/signal_unix.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT signal_unix.lo -MD -MP -MF $(DEPDIR)/signal_unix.Tpo -c -o signal_unix.lo `test -f 'runtime/signal_unix.c' || echo '$(srcdir)/'`runtime/signal_unix.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/signal_unix.Tpo $(DEPDIR)/signal_unix.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/signal_unix.c' object='signal_unix.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o signal_unix.lo `test -f 'runtime/signal_unix.c' || echo '$(srcdir)/'`runtime/signal_unix.c
|
||||
|
||||
thread.lo: runtime/thread.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread.lo -MD -MP -MF $(DEPDIR)/thread.Tpo -c -o thread.lo `test -f 'runtime/thread.c' || echo '$(srcdir)/'`runtime/thread.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/thread.Tpo $(DEPDIR)/thread.Plo
|
||||
|
@ -4327,7 +4322,7 @@ sema.c: $(srcdir)/runtime/sema.goc goc2c
|
|||
mv -f $@.tmp $@
|
||||
|
||||
sigqueue.c: $(srcdir)/runtime/sigqueue.goc goc2c
|
||||
./goc2c --gcc --go-prefix libgo_runtime $< > $@.tmp
|
||||
./goc2c --gcc --go-prefix libgo_os $< > $@.tmp
|
||||
mv -f $@.tmp $@
|
||||
|
||||
time.c: $(srcdir)/runtime/time.goc goc2c
|
||||
|
@ -4548,10 +4543,6 @@ os/check: $(CHECK_DEPS)
|
|||
@$(CHECK)
|
||||
.PHONY: os/check
|
||||
|
||||
signal_unix.go: $(srcdir)/go/os/mkunixsignals.sh sysinfo.go
|
||||
$(SHELL) $(srcdir)/go/os/mkunixsignals.sh sysinfo.go > $@.tmp
|
||||
mv -f $@.tmp $@
|
||||
|
||||
@go_include@ path/path.lo.dep
|
||||
path/path.lo.dep: $(go_path_files)
|
||||
$(BUILDDEPS)
|
||||
|
@ -5161,16 +5152,6 @@ exp/proxy/check: $(CHECK_DEPS)
|
|||
@$(CHECK)
|
||||
.PHONY: exp/proxy/check
|
||||
|
||||
@go_include@ exp/signal.lo.dep
|
||||
exp/signal.lo.dep: $(go_exp_signal_files)
|
||||
$(BUILDDEPS)
|
||||
exp/signal.lo: $(go_exp_signal_files)
|
||||
$(BUILDPACKAGE)
|
||||
exp/signal/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) exp/signal
|
||||
@$(CHECK)
|
||||
.PHONY: exp/signal/check
|
||||
|
||||
@go_include@ exp/terminal.lo.dep
|
||||
exp/terminal.lo.dep: $(go_exp_terminal_files)
|
||||
$(BUILDDEPS)
|
||||
|
@ -5622,6 +5603,16 @@ os/exec/check: $(CHECK_DEPS)
|
|||
@$(CHECK)
|
||||
.PHONY: os/exec/check
|
||||
|
||||
@go_include@ os/signal.lo.dep
|
||||
os/signal.lo.dep: $(go_os_signal_files)
|
||||
$(BUILDDEPS)
|
||||
os/signal.lo: $(go_os_signal_files)
|
||||
$(BUILDPACKAGE)
|
||||
os/signal/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) os/signal
|
||||
@$(CHECK)
|
||||
.PHONY: os/signal/check
|
||||
|
||||
@go_include@ os/user.lo.dep
|
||||
os/user.lo.dep: $(go_os_user_files)
|
||||
$(BUILDDEPS)
|
||||
|
@ -5733,16 +5724,6 @@ testing/quick/check: $(CHECK_DEPS)
|
|||
@$(CHECK)
|
||||
.PHONY: testing/quick/check
|
||||
|
||||
@go_include@ testing/script.lo.dep
|
||||
testing/script.lo.dep: $(go_testing_script_files)
|
||||
$(BUILDDEPS)
|
||||
testing/script.lo: $(go_testing_script_files)
|
||||
$(BUILDPACKAGE)
|
||||
testing/script/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) testing/script
|
||||
@$(CHECK)
|
||||
.PHONY: testing/script/check
|
||||
|
||||
@go_include@ unicode/utf16.lo.dep
|
||||
unicode/utf16.lo.dep: $(go_unicode_utf16_files)
|
||||
$(BUILDDEPS)
|
||||
|
@ -5770,6 +5751,8 @@ syscall/syscall.lo: $(go_syscall_files)
|
|||
$(BUILDPACKAGE)
|
||||
syscall/errno.lo: go/syscall/errno.c
|
||||
$(LTCOMPILE) -c -o $@ $<
|
||||
syscall/signame.lo: go/syscall/signame.c
|
||||
$(LTCOMPILE) -c -o $@ $<
|
||||
syscall/wait.lo: go/syscall/wait.c
|
||||
$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
|
@ -5941,8 +5924,6 @@ exp/norm.gox: exp/norm.lo
|
|||
$(BUILDGOX)
|
||||
exp/proxy.gox: exp/proxy.lo
|
||||
$(BUILDGOX)
|
||||
exp/signal.gox: exp/signal.lo
|
||||
$(BUILDGOX)
|
||||
exp/terminal.gox: exp/terminal.lo
|
||||
$(BUILDGOX)
|
||||
exp/types.gox: exp/types.lo
|
||||
|
@ -6043,6 +6024,8 @@ old/template.gox: old/template.lo
|
|||
|
||||
os/exec.gox: os/exec.lo
|
||||
$(BUILDGOX)
|
||||
os/signal.gox: os/signal.lo
|
||||
$(BUILDGOX)
|
||||
os/user.gox: os/user.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
|
@ -6073,8 +6056,6 @@ testing/iotest.gox: testing/iotest.lo
|
|||
$(BUILDGOX)
|
||||
testing/quick.gox: testing/quick.lo
|
||||
$(BUILDGOX)
|
||||
testing/script.gox: testing/script.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
unicode/utf16.gox: unicode/utf16.lo
|
||||
$(BUILDGOX)
|
||||
|
|
|
@ -278,7 +278,7 @@ func TestInvalidFiles(t *testing.T) {
|
|||
b := make([]byte, size)
|
||||
|
||||
// zeroes
|
||||
_, err := NewReader(sliceReaderAt(b), size)
|
||||
_, err := NewReader(bytes.NewReader(b), size)
|
||||
if err != ErrFormat {
|
||||
t.Errorf("zeroes: error=%v, want %v", err, ErrFormat)
|
||||
}
|
||||
|
@ -289,15 +289,8 @@ func TestInvalidFiles(t *testing.T) {
|
|||
for i := 0; i < size-4; i += 4 {
|
||||
copy(b[i:i+4], sig)
|
||||
}
|
||||
_, err = NewReader(sliceReaderAt(b), size)
|
||||
_, err = NewReader(bytes.NewReader(b), size)
|
||||
if err != ErrFormat {
|
||||
t.Errorf("sigs: error=%v, want %v", err, ErrFormat)
|
||||
}
|
||||
}
|
||||
|
||||
type sliceReaderAt []byte
|
||||
|
||||
func (r sliceReaderAt) ReadAt(b []byte, off int64) (int, error) {
|
||||
copy(b, r[int(off):int(off)+len(b)])
|
||||
return len(b), nil
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
|
||||
// Writer implements a zip file writer.
|
||||
type Writer struct {
|
||||
countWriter
|
||||
cw *countWriter
|
||||
dir []*header
|
||||
last *fileWriter
|
||||
closed bool
|
||||
|
@ -32,7 +32,7 @@ type header struct {
|
|||
|
||||
// NewWriter returns a new Writer writing a zip file to w.
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
return &Writer{countWriter: countWriter{w: bufio.NewWriter(w)}}
|
||||
return &Writer{cw: &countWriter{w: bufio.NewWriter(w)}}
|
||||
}
|
||||
|
||||
// Close finishes writing the zip file by writing the central directory.
|
||||
|
@ -52,42 +52,42 @@ func (w *Writer) Close() (err error) {
|
|||
defer recoverError(&err)
|
||||
|
||||
// write central directory
|
||||
start := w.count
|
||||
start := w.cw.count
|
||||
for _, h := range w.dir {
|
||||
write(w, uint32(directoryHeaderSignature))
|
||||
write(w, h.CreatorVersion)
|
||||
write(w, h.ReaderVersion)
|
||||
write(w, h.Flags)
|
||||
write(w, h.Method)
|
||||
write(w, h.ModifiedTime)
|
||||
write(w, h.ModifiedDate)
|
||||
write(w, h.CRC32)
|
||||
write(w, h.CompressedSize)
|
||||
write(w, h.UncompressedSize)
|
||||
write(w, uint16(len(h.Name)))
|
||||
write(w, uint16(len(h.Extra)))
|
||||
write(w, uint16(len(h.Comment)))
|
||||
write(w, uint16(0)) // disk number start
|
||||
write(w, uint16(0)) // internal file attributes
|
||||
write(w, h.ExternalAttrs)
|
||||
write(w, h.offset)
|
||||
writeBytes(w, []byte(h.Name))
|
||||
writeBytes(w, h.Extra)
|
||||
writeBytes(w, []byte(h.Comment))
|
||||
write(w.cw, uint32(directoryHeaderSignature))
|
||||
write(w.cw, h.CreatorVersion)
|
||||
write(w.cw, h.ReaderVersion)
|
||||
write(w.cw, h.Flags)
|
||||
write(w.cw, h.Method)
|
||||
write(w.cw, h.ModifiedTime)
|
||||
write(w.cw, h.ModifiedDate)
|
||||
write(w.cw, h.CRC32)
|
||||
write(w.cw, h.CompressedSize)
|
||||
write(w.cw, h.UncompressedSize)
|
||||
write(w.cw, uint16(len(h.Name)))
|
||||
write(w.cw, uint16(len(h.Extra)))
|
||||
write(w.cw, uint16(len(h.Comment)))
|
||||
write(w.cw, uint16(0)) // disk number start
|
||||
write(w.cw, uint16(0)) // internal file attributes
|
||||
write(w.cw, h.ExternalAttrs)
|
||||
write(w.cw, h.offset)
|
||||
writeBytes(w.cw, []byte(h.Name))
|
||||
writeBytes(w.cw, h.Extra)
|
||||
writeBytes(w.cw, []byte(h.Comment))
|
||||
}
|
||||
end := w.count
|
||||
end := w.cw.count
|
||||
|
||||
// write end record
|
||||
write(w, uint32(directoryEndSignature))
|
||||
write(w, uint16(0)) // disk number
|
||||
write(w, uint16(0)) // disk number where directory starts
|
||||
write(w, uint16(len(w.dir))) // number of entries this disk
|
||||
write(w, uint16(len(w.dir))) // number of entries total
|
||||
write(w, uint32(end-start)) // size of directory
|
||||
write(w, uint32(start)) // start of directory
|
||||
write(w, uint16(0)) // size of comment
|
||||
write(w.cw, uint32(directoryEndSignature))
|
||||
write(w.cw, uint16(0)) // disk number
|
||||
write(w.cw, uint16(0)) // disk number where directory starts
|
||||
write(w.cw, uint16(len(w.dir))) // number of entries this disk
|
||||
write(w.cw, uint16(len(w.dir))) // number of entries total
|
||||
write(w.cw, uint32(end-start)) // size of directory
|
||||
write(w.cw, uint32(start)) // start of directory
|
||||
write(w.cw, uint16(0)) // size of comment
|
||||
|
||||
return w.w.(*bufio.Writer).Flush()
|
||||
return w.cw.w.(*bufio.Writer).Flush()
|
||||
}
|
||||
|
||||
// Create adds a file to the zip file using the provided name.
|
||||
|
@ -119,15 +119,19 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
|
|||
fh.ReaderVersion = 0x14
|
||||
|
||||
fw := &fileWriter{
|
||||
zipw: w,
|
||||
compCount: &countWriter{w: w},
|
||||
zipw: w.cw,
|
||||
compCount: &countWriter{w: w.cw},
|
||||
crc32: crc32.NewIEEE(),
|
||||
}
|
||||
switch fh.Method {
|
||||
case Store:
|
||||
fw.comp = nopCloser{fw.compCount}
|
||||
case Deflate:
|
||||
fw.comp = flate.NewWriter(fw.compCount, 5)
|
||||
var err error
|
||||
fw.comp, err = flate.NewWriter(fw.compCount, 5)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, ErrAlgorithm
|
||||
}
|
||||
|
@ -135,12 +139,12 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
|
|||
|
||||
h := &header{
|
||||
FileHeader: fh,
|
||||
offset: uint32(w.count),
|
||||
offset: uint32(w.cw.count),
|
||||
}
|
||||
w.dir = append(w.dir, h)
|
||||
fw.header = h
|
||||
|
||||
if err := writeHeader(w, fh); err != nil {
|
||||
if err := writeHeader(w.cw, fh); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ func TestWriter(t *testing.T) {
|
|||
}
|
||||
|
||||
// read it back
|
||||
r, err := NewReader(sliceReaderAt(buf.Bytes()), int64(buf.Len()))
|
||||
r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -9,22 +9,12 @@ package zip
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type stringReaderAt string
|
||||
|
||||
func (s stringReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
|
||||
if off >= int64(len(s)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n = copy(p, s[off:])
|
||||
return
|
||||
}
|
||||
|
||||
func TestOver65kFiles(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Logf("slow test; skipping")
|
||||
|
@ -42,8 +32,8 @@ func TestOver65kFiles(t *testing.T) {
|
|||
if err := w.Close(); err != nil {
|
||||
t.Fatalf("Writer.Close: %v", err)
|
||||
}
|
||||
rat := stringReaderAt(buf.String())
|
||||
zr, err := NewReader(rat, int64(len(rat)))
|
||||
s := buf.String()
|
||||
zr, err := NewReader(strings.NewReader(s), int64(len(s)))
|
||||
if err != nil {
|
||||
t.Fatalf("NewReader: %v", err)
|
||||
}
|
||||
|
|
|
@ -182,14 +182,21 @@ func makeSlice(n int) []byte {
|
|||
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
|
||||
b.lastRead = opInvalid
|
||||
if b.off < len(b.buf) {
|
||||
nBytes := b.Len()
|
||||
m, e := w.Write(b.buf[b.off:])
|
||||
if m > nBytes {
|
||||
panic("bytes.Buffer.WriteTo: invalid Write count")
|
||||
}
|
||||
b.off += m
|
||||
n = int64(m)
|
||||
if e != nil {
|
||||
return n, e
|
||||
}
|
||||
// otherwise all bytes were written, by definition of
|
||||
// all bytes should have been written, by definition of
|
||||
// Write method in io.Writer
|
||||
if m != nBytes {
|
||||
return n, io.ErrShortWrite
|
||||
}
|
||||
}
|
||||
// Buffer is now empty; reset.
|
||||
b.Truncate(0)
|
||||
|
|
125
libgo/go/bytes/reader.go
Normal file
125
libgo/go/bytes/reader.go
Normal file
|
@ -0,0 +1,125 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bytes
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// A Reader implements the io.Reader, io.ReaderAt, io.Seeker,
|
||||
// io.ByteScanner, and io.RuneScanner interfaces by reading from
|
||||
// a byte slice.
|
||||
// Unlike a Buffer, a Reader is read-only and supports seeking.
|
||||
type Reader struct {
|
||||
s []byte
|
||||
i int // current reading index
|
||||
prevRune int // index of previous rune; or < 0
|
||||
}
|
||||
|
||||
// Len returns the number of bytes of the unread portion of the
|
||||
// slice.
|
||||
func (r *Reader) Len() int {
|
||||
if r.i >= len(r.s) {
|
||||
return 0
|
||||
}
|
||||
return len(r.s) - r.i
|
||||
}
|
||||
|
||||
func (r *Reader) Read(b []byte) (n int, err error) {
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
if r.i >= len(r.s) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n = copy(b, r.s[r.i:])
|
||||
r.i += n
|
||||
r.prevRune = -1
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
if off < 0 {
|
||||
return 0, errors.New("bytes: invalid offset")
|
||||
}
|
||||
if off >= int64(len(r.s)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n = copy(b, r.s[int(off):])
|
||||
if n < len(b) {
|
||||
err = io.EOF
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Reader) ReadByte() (b byte, err error) {
|
||||
if r.i >= len(r.s) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
b = r.s[r.i]
|
||||
r.i++
|
||||
r.prevRune = -1
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Reader) UnreadByte() error {
|
||||
if r.i <= 0 {
|
||||
return errors.New("bytes.Reader: at beginning of slice")
|
||||
}
|
||||
r.i--
|
||||
r.prevRune = -1
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Reader) ReadRune() (ch rune, size int, err error) {
|
||||
if r.i >= len(r.s) {
|
||||
return 0, 0, io.EOF
|
||||
}
|
||||
r.prevRune = r.i
|
||||
if c := r.s[r.i]; c < utf8.RuneSelf {
|
||||
r.i++
|
||||
return rune(c), 1, nil
|
||||
}
|
||||
ch, size = utf8.DecodeRune(r.s[r.i:])
|
||||
r.i += size
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Reader) UnreadRune() error {
|
||||
if r.prevRune < 0 {
|
||||
return errors.New("bytes.Reader: previous operation was not ReadRune")
|
||||
}
|
||||
r.i = r.prevRune
|
||||
r.prevRune = -1
|
||||
return nil
|
||||
}
|
||||
|
||||
// Seek implements the io.Seeker interface.
|
||||
func (r *Reader) Seek(offset int64, whence int) (int64, error) {
|
||||
var abs int64
|
||||
switch whence {
|
||||
case 0:
|
||||
abs = offset
|
||||
case 1:
|
||||
abs = int64(r.i) + offset
|
||||
case 2:
|
||||
abs = int64(len(r.s)) + offset
|
||||
default:
|
||||
return 0, errors.New("bytes: invalid whence")
|
||||
}
|
||||
if abs < 0 {
|
||||
return 0, errors.New("bytes: negative position")
|
||||
}
|
||||
if abs >= 1<<31 {
|
||||
return 0, errors.New("bytes: position out of range")
|
||||
}
|
||||
r.i = int(abs)
|
||||
return abs, nil
|
||||
}
|
||||
|
||||
// NewReader returns a new Reader reading from b.
|
||||
func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }
|
88
libgo/go/bytes/reader_test.go
Normal file
88
libgo/go/bytes/reader_test.go
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bytes_test
|
||||
|
||||
import (
|
||||
. "bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReader(t *testing.T) {
|
||||
r := NewReader([]byte("0123456789"))
|
||||
tests := []struct {
|
||||
off int64
|
||||
seek int
|
||||
n int
|
||||
want string
|
||||
wantpos int64
|
||||
seekerr string
|
||||
}{
|
||||
{seek: os.SEEK_SET, off: 0, n: 20, want: "0123456789"},
|
||||
{seek: os.SEEK_SET, off: 1, n: 1, want: "1"},
|
||||
{seek: os.SEEK_CUR, off: 1, wantpos: 3, n: 2, want: "34"},
|
||||
{seek: os.SEEK_SET, off: -1, seekerr: "bytes: negative position"},
|
||||
{seek: os.SEEK_SET, off: 1<<31 - 1},
|
||||
{seek: os.SEEK_CUR, off: 1, seekerr: "bytes: position out of range"},
|
||||
{seek: os.SEEK_SET, n: 5, want: "01234"},
|
||||
{seek: os.SEEK_CUR, n: 5, want: "56789"},
|
||||
{seek: os.SEEK_END, off: -1, n: 1, wantpos: 9, want: "9"},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
pos, err := r.Seek(tt.off, tt.seek)
|
||||
if err == nil && tt.seekerr != "" {
|
||||
t.Errorf("%d. want seek error %q", i, tt.seekerr)
|
||||
continue
|
||||
}
|
||||
if err != nil && err.Error() != tt.seekerr {
|
||||
t.Errorf("%d. seek error = %q; want %q", i, err.Error(), tt.seekerr)
|
||||
continue
|
||||
}
|
||||
if tt.wantpos != 0 && tt.wantpos != pos {
|
||||
t.Errorf("%d. pos = %d, want %d", i, pos, tt.wantpos)
|
||||
}
|
||||
buf := make([]byte, tt.n)
|
||||
n, err := r.Read(buf)
|
||||
if err != nil {
|
||||
t.Errorf("%d. read = %v", i, err)
|
||||
continue
|
||||
}
|
||||
got := string(buf[:n])
|
||||
if got != tt.want {
|
||||
t.Errorf("%d. got %q; want %q", i, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReaderAt(t *testing.T) {
|
||||
r := NewReader([]byte("0123456789"))
|
||||
tests := []struct {
|
||||
off int64
|
||||
n int
|
||||
want string
|
||||
wanterr interface{}
|
||||
}{
|
||||
{0, 10, "0123456789", nil},
|
||||
{1, 10, "123456789", io.EOF},
|
||||
{1, 9, "123456789", nil},
|
||||
{11, 10, "", io.EOF},
|
||||
{0, 0, "", nil},
|
||||
{-1, 0, "", "bytes: invalid offset"},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
b := make([]byte, tt.n)
|
||||
rn, err := r.ReadAt(b, tt.off)
|
||||
got := string(b[:rn])
|
||||
if got != tt.want {
|
||||
t.Errorf("%d. got %q; want %q", i, got, tt.want)
|
||||
}
|
||||
if fmt.Sprintf("%v", err) != fmt.Sprintf("%v", tt.wanterr) {
|
||||
t.Errorf("%d. got error = %v; want %v", i, err, tt.wanterr)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
package flate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
)
|
||||
|
@ -390,7 +391,7 @@ func (d *compressor) init(w io.Writer, level int) (err error) {
|
|||
d.fill = (*compressor).fillDeflate
|
||||
d.step = (*compressor).deflate
|
||||
default:
|
||||
return WrongValueError{"level", 0, 9, int32(level)}
|
||||
return fmt.Errorf("flate: invalid compression level %d: want value in range [-1, 9]", level)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -408,17 +409,22 @@ func (d *compressor) close() error {
|
|||
return d.w.err
|
||||
}
|
||||
|
||||
// NewWriter returns a new Writer compressing
|
||||
// data at the given level. Following zlib, levels
|
||||
// range from 1 (BestSpeed) to 9 (BestCompression);
|
||||
// higher levels typically run slower but compress more.
|
||||
// Level 0 (NoCompression) does not attempt any
|
||||
// compression; it only adds the necessary DEFLATE framing.
|
||||
func NewWriter(w io.Writer, level int) *Writer {
|
||||
// NewWriter returns a new Writer compressing data at the given level.
|
||||
// Following zlib, levels range from 1 (BestSpeed) to 9 (BestCompression);
|
||||
// higher levels typically run slower but compress more. Level 0
|
||||
// (NoCompression) does not attempt any compression; it only adds the
|
||||
// necessary DEFLATE framing. Level -1 (DefaultCompression) uses the default
|
||||
// compression level.
|
||||
//
|
||||
// If level is in the range [-1, 9] then the error returned will be nil.
|
||||
// Otherwise the error returned will be non-nil.
|
||||
func NewWriter(w io.Writer, level int) (*Writer, error) {
|
||||
const logWindowSize = logMaxOffsetSize
|
||||
var dw Writer
|
||||
dw.d.init(w, level)
|
||||
return &dw
|
||||
if err := dw.d.init(w, level); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dw, nil
|
||||
}
|
||||
|
||||
// NewWriterDict is like NewWriter but initializes the new
|
||||
|
@ -427,13 +433,16 @@ func NewWriter(w io.Writer, level int) *Writer {
|
|||
// any compressed output. The compressed data written to w
|
||||
// can only be decompressed by a Reader initialized with the
|
||||
// same dictionary.
|
||||
func NewWriterDict(w io.Writer, level int, dict []byte) *Writer {
|
||||
func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) {
|
||||
dw := &dictWriter{w, false}
|
||||
zw := NewWriter(dw, level)
|
||||
zw, err := NewWriter(dw, level)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zw.Write(dict)
|
||||
zw.Flush()
|
||||
dw.enabled = true
|
||||
return zw
|
||||
return zw, err
|
||||
}
|
||||
|
||||
type dictWriter struct {
|
||||
|
|
|
@ -81,7 +81,11 @@ func largeDataChunk() []byte {
|
|||
func TestDeflate(t *testing.T) {
|
||||
for _, h := range deflateTests {
|
||||
var buf bytes.Buffer
|
||||
w := NewWriter(&buf, h.level)
|
||||
w, err := NewWriter(&buf, h.level)
|
||||
if err != nil {
|
||||
t.Errorf("NewWriter: %v", err)
|
||||
continue
|
||||
}
|
||||
w.Write(h.in)
|
||||
w.Close()
|
||||
if !bytes.Equal(buf.Bytes(), h.out) {
|
||||
|
@ -151,7 +155,11 @@ func testSync(t *testing.T, level int, input []byte, name string) {
|
|||
buf := newSyncBuffer()
|
||||
buf1 := new(bytes.Buffer)
|
||||
buf.WriteMode()
|
||||
w := NewWriter(io.MultiWriter(buf, buf1), level)
|
||||
w, err := NewWriter(io.MultiWriter(buf, buf1), level)
|
||||
if err != nil {
|
||||
t.Errorf("NewWriter: %v", err)
|
||||
return
|
||||
}
|
||||
r := NewReader(buf)
|
||||
|
||||
// Write half the input and read back.
|
||||
|
@ -213,7 +221,7 @@ func testSync(t *testing.T, level int, input []byte, name string) {
|
|||
|
||||
// stream should work for ordinary reader too
|
||||
r = NewReader(buf1)
|
||||
out, err := ioutil.ReadAll(r)
|
||||
out, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Errorf("testSync: read: %s", err)
|
||||
return
|
||||
|
@ -224,31 +232,31 @@ func testSync(t *testing.T, level int, input []byte, name string) {
|
|||
}
|
||||
}
|
||||
|
||||
func testToFromWithLevel(t *testing.T, level int, input []byte, name string) error {
|
||||
return testToFromWithLevelAndLimit(t, level, input, name, -1)
|
||||
}
|
||||
|
||||
func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) error {
|
||||
func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) {
|
||||
var buffer bytes.Buffer
|
||||
w := NewWriter(&buffer, level)
|
||||
w, err := NewWriter(&buffer, level)
|
||||
if err != nil {
|
||||
t.Errorf("NewWriter: %v", err)
|
||||
return
|
||||
}
|
||||
w.Write(input)
|
||||
w.Close()
|
||||
if limit > 0 && buffer.Len() > limit {
|
||||
t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit)
|
||||
return
|
||||
}
|
||||
r := NewReader(&buffer)
|
||||
out, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Errorf("read: %s", err)
|
||||
return err
|
||||
return
|
||||
}
|
||||
r.Close()
|
||||
if !bytes.Equal(input, out) {
|
||||
t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name)
|
||||
return
|
||||
}
|
||||
|
||||
testSync(t, level, input, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func testToFromWithLimit(t *testing.T, input []byte, name string, limit [10]int) {
|
||||
|
@ -257,13 +265,9 @@ func testToFromWithLimit(t *testing.T, input []byte, name string, limit [10]int)
|
|||
}
|
||||
}
|
||||
|
||||
func testToFrom(t *testing.T, input []byte, name string) {
|
||||
testToFromWithLimit(t, input, name, [10]int{})
|
||||
}
|
||||
|
||||
func TestDeflateInflate(t *testing.T) {
|
||||
for i, h := range deflateInflateTests {
|
||||
testToFrom(t, h.in, fmt.Sprintf("#%d", i))
|
||||
testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [10]int{})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,7 +315,10 @@ func TestReaderDict(t *testing.T) {
|
|||
text = "hello again world"
|
||||
)
|
||||
var b bytes.Buffer
|
||||
w := NewWriter(&b, 5)
|
||||
w, err := NewWriter(&b, 5)
|
||||
if err != nil {
|
||||
t.Fatalf("NewWriter: %v", err)
|
||||
}
|
||||
w.Write([]byte(dict))
|
||||
w.Flush()
|
||||
b.Reset()
|
||||
|
@ -334,7 +341,10 @@ func TestWriterDict(t *testing.T) {
|
|||
text = "hello again world"
|
||||
)
|
||||
var b bytes.Buffer
|
||||
w := NewWriter(&b, 5)
|
||||
w, err := NewWriter(&b, 5)
|
||||
if err != nil {
|
||||
t.Fatalf("NewWriter: %v", err)
|
||||
}
|
||||
w.Write([]byte(dict))
|
||||
w.Flush()
|
||||
b.Reset()
|
||||
|
@ -342,7 +352,7 @@ func TestWriterDict(t *testing.T) {
|
|||
w.Close()
|
||||
|
||||
var b1 bytes.Buffer
|
||||
w = NewWriterDict(&b1, 5, []byte(dict))
|
||||
w, _ = NewWriterDict(&b1, 5, []byte(dict))
|
||||
w.Write([]byte(text))
|
||||
w.Close()
|
||||
|
||||
|
@ -353,7 +363,10 @@ func TestWriterDict(t *testing.T) {
|
|||
|
||||
// See http://code.google.com/p/go/issues/detail?id=2508
|
||||
func TestRegression2508(t *testing.T) {
|
||||
w := NewWriter(ioutil.Discard, 1)
|
||||
w, err := NewWriter(ioutil.Discard, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("NewWriter: %v", err)
|
||||
}
|
||||
buf := make([]byte, 1024)
|
||||
for i := 0; i < 131072; i++ {
|
||||
if _, err := w.Write(buf); err != nil {
|
||||
|
|
|
@ -7,7 +7,6 @@ package flate
|
|||
import (
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -85,13 +84,6 @@ type huffmanBitWriter struct {
|
|||
err error
|
||||
}
|
||||
|
||||
type WrongValueError struct {
|
||||
name string
|
||||
from int32
|
||||
to int32
|
||||
value int32
|
||||
}
|
||||
|
||||
func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
|
||||
return &huffmanBitWriter{
|
||||
w: w,
|
||||
|
@ -105,11 +97,6 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
|
|||
}
|
||||
}
|
||||
|
||||
func (err WrongValueError) Error() string {
|
||||
return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.FormatInt(int64(err.from), 10) + ";" +
|
||||
strconv.FormatInt(int64(err.to), 10) + "] but actual value is " + strconv.FormatInt(int64(err.value), 10)
|
||||
}
|
||||
|
||||
func (w *huffmanBitWriter) flushBits() {
|
||||
if w.err != nil {
|
||||
w.nbits = 0
|
||||
|
|
|
@ -16,9 +16,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// BUG(nigeltao): Comments and Names don't properly map UTF-8 character codes outside of
|
||||
// the 0x00-0x7f range to ISO 8859-1 (Latin-1).
|
||||
|
||||
const (
|
||||
gzipID1 = 0x1f
|
||||
gzipID2 = 0x8b
|
||||
|
@ -37,11 +34,15 @@ func makeReader(r io.Reader) flate.Reader {
|
|||
return bufio.NewReader(r)
|
||||
}
|
||||
|
||||
var ErrHeader = errors.New("invalid gzip header")
|
||||
var ErrChecksum = errors.New("gzip checksum error")
|
||||
var (
|
||||
// ErrChecksum is returned when reading GZIP data that has an invalid checksum.
|
||||
ErrChecksum = errors.New("gzip: invalid checksum")
|
||||
// ErrHeader is returned when reading GZIP data that has an invalid header.
|
||||
ErrHeader = errors.New("gzip: invalid header")
|
||||
)
|
||||
|
||||
// The gzip file stores a header giving metadata about the compressed file.
|
||||
// That header is exposed as the fields of the Compressor and Decompressor structs.
|
||||
// That header is exposed as the fields of the Writer and Reader structs.
|
||||
type Header struct {
|
||||
Comment string // comment
|
||||
Extra []byte // "extra data"
|
||||
|
@ -50,21 +51,21 @@ type Header struct {
|
|||
OS byte // operating system type
|
||||
}
|
||||
|
||||
// An Decompressor is an io.Reader that can be read to retrieve
|
||||
// A Reader is an io.Reader that can be read to retrieve
|
||||
// uncompressed data from a gzip-format compressed file.
|
||||
//
|
||||
// In general, a gzip file can be a concatenation of gzip files,
|
||||
// each with its own header. Reads from the Decompressor
|
||||
// each with its own header. Reads from the Reader
|
||||
// return the concatenation of the uncompressed data of each.
|
||||
// Only the first header is recorded in the Decompressor fields.
|
||||
// Only the first header is recorded in the Reader fields.
|
||||
//
|
||||
// Gzip files store a length and checksum of the uncompressed data.
|
||||
// The Decompressor will return a ErrChecksum when Read
|
||||
// The Reader will return a ErrChecksum when Read
|
||||
// reaches the end of the uncompressed data if it does not
|
||||
// have the expected length or checksum. Clients should treat data
|
||||
// returned by Read as tentative until they receive the successful
|
||||
// (zero length, nil error) Read marking the end of the data.
|
||||
type Decompressor struct {
|
||||
// returned by Read as tentative until they receive the io.EOF
|
||||
// marking the end of the data.
|
||||
type Reader struct {
|
||||
Header
|
||||
r flate.Reader
|
||||
decompressor io.ReadCloser
|
||||
|
@ -75,15 +76,14 @@ type Decompressor struct {
|
|||
err error
|
||||
}
|
||||
|
||||
// NewReader creates a new Decompressor reading the given reader.
|
||||
// NewReader creates a new Reader reading the given reader.
|
||||
// The implementation buffers input and may read more data than necessary from r.
|
||||
// It is the caller's responsibility to call Close on the Decompressor when done.
|
||||
func NewReader(r io.Reader) (*Decompressor, error) {
|
||||
z := new(Decompressor)
|
||||
// It is the caller's responsibility to call Close on the Reader when done.
|
||||
func NewReader(r io.Reader) (*Reader, error) {
|
||||
z := new(Reader)
|
||||
z.r = makeReader(r)
|
||||
z.digest = crc32.NewIEEE()
|
||||
if err := z.readHeader(true); err != nil {
|
||||
z.err = err
|
||||
return nil, err
|
||||
}
|
||||
return z, nil
|
||||
|
@ -94,7 +94,7 @@ func get4(p []byte) uint32 {
|
|||
return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
|
||||
}
|
||||
|
||||
func (z *Decompressor) readString() (string, error) {
|
||||
func (z *Reader) readString() (string, error) {
|
||||
var err error
|
||||
needconv := false
|
||||
for i := 0; ; i++ {
|
||||
|
@ -123,7 +123,7 @@ func (z *Decompressor) readString() (string, error) {
|
|||
panic("not reached")
|
||||
}
|
||||
|
||||
func (z *Decompressor) read2() (uint32, error) {
|
||||
func (z *Reader) read2() (uint32, error) {
|
||||
_, err := io.ReadFull(z.r, z.buf[0:2])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -131,7 +131,7 @@ func (z *Decompressor) read2() (uint32, error) {
|
|||
return uint32(z.buf[0]) | uint32(z.buf[1])<<8, nil
|
||||
}
|
||||
|
||||
func (z *Decompressor) readHeader(save bool) error {
|
||||
func (z *Reader) readHeader(save bool) error {
|
||||
_, err := io.ReadFull(z.r, z.buf[0:10])
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -197,7 +197,7 @@ func (z *Decompressor) readHeader(save bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (z *Decompressor) Read(p []byte) (n int, err error) {
|
||||
func (z *Reader) Read(p []byte) (n int, err error) {
|
||||
if z.err != nil {
|
||||
return 0, z.err
|
||||
}
|
||||
|
@ -237,5 +237,5 @@ func (z *Decompressor) Read(p []byte) (n int, err error) {
|
|||
return z.Read(p)
|
||||
}
|
||||
|
||||
// Calling Close does not close the wrapped io.Reader originally passed to NewReader.
|
||||
func (z *Decompressor) Close() error { return z.decompressor.Close() }
|
||||
// Close closes the Reader. It does not close the underlying io.Reader.
|
||||
func (z *Reader) Close() error { return z.decompressor.Close() }
|
||||
|
|
|
@ -7,6 +7,7 @@ package gzip
|
|||
import (
|
||||
"compress/flate"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
|
@ -21,9 +22,9 @@ const (
|
|||
DefaultCompression = flate.DefaultCompression
|
||||
)
|
||||
|
||||
// A Compressor is an io.WriteCloser that satisfies writes by compressing data written
|
||||
// A Writer is an io.WriteCloser that satisfies writes by compressing data written
|
||||
// to its wrapped io.Writer.
|
||||
type Compressor struct {
|
||||
type Writer struct {
|
||||
Header
|
||||
w io.Writer
|
||||
level int
|
||||
|
@ -35,25 +36,40 @@ type Compressor struct {
|
|||
err error
|
||||
}
|
||||
|
||||
// NewWriter calls NewWriterLevel with the default compression level.
|
||||
func NewWriter(w io.Writer) (*Compressor, error) {
|
||||
return NewWriterLevel(w, DefaultCompression)
|
||||
// NewWriter creates a new Writer that satisfies writes by compressing data
|
||||
// written to w.
|
||||
//
|
||||
// It is the caller's responsibility to call Close on the WriteCloser when done.
|
||||
// Writes may be buffered and not flushed until Close.
|
||||
//
|
||||
// Callers that wish to set the fields in Writer.Header must do so before
|
||||
// the first call to Write or Close. The Comment and Name header fields are
|
||||
// UTF-8 strings in Go, but the underlying format requires NUL-terminated ISO
|
||||
// 8859-1 (Latin-1). NUL or non-Latin-1 runes in those strings will lead to an
|
||||
// error on Write.
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
z, _ := NewWriterLevel(w, DefaultCompression)
|
||||
return z
|
||||
}
|
||||
|
||||
// NewWriterLevel creates a new Compressor writing to the given writer.
|
||||
// Writes may be buffered and not flushed until Close.
|
||||
// Callers that wish to set the fields in Compressor.Header must
|
||||
// do so before the first call to Write or Close.
|
||||
// It is the caller's responsibility to call Close on the WriteCloser when done.
|
||||
// level is the compression level, which can be DefaultCompression, NoCompression,
|
||||
// or any integer value between BestSpeed and BestCompression (inclusive).
|
||||
func NewWriterLevel(w io.Writer, level int) (*Compressor, error) {
|
||||
z := new(Compressor)
|
||||
z.OS = 255 // unknown
|
||||
z.w = w
|
||||
z.level = level
|
||||
z.digest = crc32.NewIEEE()
|
||||
return z, nil
|
||||
// NewWriterLevel is like NewWriter but specifies the compression level instead
|
||||
// of assuming DefaultCompression.
|
||||
//
|
||||
// The compression level can be DefaultCompression, NoCompression, or any
|
||||
// integer value between BestSpeed and BestCompression inclusive. The error
|
||||
// returned will be nil if the level is valid.
|
||||
func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
|
||||
if level < DefaultCompression || level > BestCompression {
|
||||
return nil, fmt.Errorf("gzip: invalid compression level: %d", level)
|
||||
}
|
||||
return &Writer{
|
||||
Header: Header{
|
||||
OS: 255, // unknown
|
||||
},
|
||||
w: w,
|
||||
level: level,
|
||||
digest: crc32.NewIEEE(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
|
||||
|
@ -70,7 +86,7 @@ func put4(p []byte, v uint32) {
|
|||
}
|
||||
|
||||
// writeBytes writes a length-prefixed byte slice to z.w.
|
||||
func (z *Compressor) writeBytes(b []byte) error {
|
||||
func (z *Writer) writeBytes(b []byte) error {
|
||||
if len(b) > 0xffff {
|
||||
return errors.New("gzip.Write: Extra data is too large")
|
||||
}
|
||||
|
@ -83,10 +99,10 @@ func (z *Compressor) writeBytes(b []byte) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// writeString writes a string (in ISO 8859-1 (Latin-1) format) to z.w.
|
||||
func (z *Compressor) writeString(s string) error {
|
||||
// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
|
||||
var err error
|
||||
// writeString writes a UTF-8 string s in GZIP's format to z.w.
|
||||
// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
|
||||
func (z *Writer) writeString(s string) (err error) {
|
||||
// GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII.
|
||||
needconv := false
|
||||
for _, v := range s {
|
||||
if v == 0 || v > 0xff {
|
||||
|
@ -114,7 +130,9 @@ func (z *Compressor) writeString(s string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (z *Compressor) Write(p []byte) (int, error) {
|
||||
// Write writes a compressed form of p to the underlying io.Writer. The
|
||||
// compressed bytes are not necessarily flushed until the Writer is closed.
|
||||
func (z *Writer) Write(p []byte) (int, error) {
|
||||
if z.err != nil {
|
||||
return 0, z.err
|
||||
}
|
||||
|
@ -165,7 +183,7 @@ func (z *Compressor) Write(p []byte) (int, error) {
|
|||
return n, z.err
|
||||
}
|
||||
}
|
||||
z.compressor = flate.NewWriter(z.w, z.level)
|
||||
z.compressor, _ = flate.NewWriter(z.w, z.level)
|
||||
}
|
||||
z.size += uint32(len(p))
|
||||
z.digest.Write(p)
|
||||
|
@ -173,8 +191,8 @@ func (z *Compressor) Write(p []byte) (int, error) {
|
|||
return n, z.err
|
||||
}
|
||||
|
||||
// Calling Close does not close the wrapped io.Writer originally passed to NewWriter.
|
||||
func (z *Compressor) Close() error {
|
||||
// Close closes the Writer. It does not close the underlying io.Writer.
|
||||
func (z *Writer) Close() error {
|
||||
if z.err != nil {
|
||||
return z.err
|
||||
}
|
||||
|
|
|
@ -7,108 +7,153 @@ package gzip
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// pipe creates two ends of a pipe that gzip and gunzip, and runs dfunc at the
|
||||
// writer end and cfunc at the reader end.
|
||||
func pipe(t *testing.T, dfunc func(*Compressor), cfunc func(*Decompressor)) {
|
||||
piper, pipew := io.Pipe()
|
||||
defer piper.Close()
|
||||
go func() {
|
||||
defer pipew.Close()
|
||||
compressor, err := NewWriter(pipew)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
defer compressor.Close()
|
||||
dfunc(compressor)
|
||||
}()
|
||||
decompressor, err := NewReader(piper)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
defer decompressor.Close()
|
||||
cfunc(decompressor)
|
||||
}
|
||||
|
||||
// Tests that an empty payload still forms a valid GZIP stream.
|
||||
// TestEmpty tests that an empty payload still forms a valid GZIP stream.
|
||||
func TestEmpty(t *testing.T) {
|
||||
pipe(t,
|
||||
func(compressor *Compressor) {},
|
||||
func(decompressor *Decompressor) {
|
||||
b, err := ioutil.ReadAll(decompressor)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
if len(b) != 0 {
|
||||
t.Fatalf("did not read an empty slice")
|
||||
}
|
||||
})
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
if err := NewWriter(buf).Close(); err != nil {
|
||||
t.Fatalf("Writer.Close: %v", err)
|
||||
}
|
||||
|
||||
r, err := NewReader(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("NewReader: %v", err)
|
||||
}
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadAll: %v", err)
|
||||
}
|
||||
if len(b) != 0 {
|
||||
t.Fatalf("got %d bytes, want 0", len(b))
|
||||
}
|
||||
if err := r.Close(); err != nil {
|
||||
t.Fatalf("Reader.Close: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that gzipping and then gunzipping is the identity function.
|
||||
func TestWriter(t *testing.T) {
|
||||
pipe(t,
|
||||
func(compressor *Compressor) {
|
||||
compressor.Comment = "Äußerung"
|
||||
//compressor.Comment = "comment"
|
||||
compressor.Extra = []byte("extra")
|
||||
compressor.ModTime = time.Unix(1e8, 0)
|
||||
compressor.Name = "name"
|
||||
_, err := compressor.Write([]byte("payload"))
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
},
|
||||
func(decompressor *Decompressor) {
|
||||
b, err := ioutil.ReadAll(decompressor)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
if string(b) != "payload" {
|
||||
t.Fatalf("payload is %q, want %q", string(b), "payload")
|
||||
}
|
||||
if decompressor.Comment != "Äußerung" {
|
||||
t.Fatalf("comment is %q, want %q", decompressor.Comment, "Äußerung")
|
||||
}
|
||||
if string(decompressor.Extra) != "extra" {
|
||||
t.Fatalf("extra is %q, want %q", decompressor.Extra, "extra")
|
||||
}
|
||||
if decompressor.ModTime.Unix() != 1e8 {
|
||||
t.Fatalf("mtime is %d, want %d", decompressor.ModTime.Unix(), uint32(1e8))
|
||||
}
|
||||
if decompressor.Name != "name" {
|
||||
t.Fatalf("name is %q, want %q", decompressor.Name, "name")
|
||||
}
|
||||
})
|
||||
// TestRoundTrip tests that gzipping and then gunzipping is the identity
|
||||
// function.
|
||||
func TestRoundTrip(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
w := NewWriter(buf)
|
||||
w.Comment = "comment"
|
||||
w.Extra = []byte("extra")
|
||||
w.ModTime = time.Unix(1e8, 0)
|
||||
w.Name = "name"
|
||||
if _, err := w.Write([]byte("payload")); err != nil {
|
||||
t.Fatalf("Write: %v", err)
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
t.Fatalf("Writer.Close: %v", err)
|
||||
}
|
||||
|
||||
r, err := NewReader(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("NewReader: %v", err)
|
||||
}
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadAll: %v", err)
|
||||
}
|
||||
if string(b) != "payload" {
|
||||
t.Fatalf("payload is %q, want %q", string(b), "payload")
|
||||
}
|
||||
if r.Comment != "comment" {
|
||||
t.Fatalf("comment is %q, want %q", r.Comment, "comment")
|
||||
}
|
||||
if string(r.Extra) != "extra" {
|
||||
t.Fatalf("extra is %q, want %q", r.Extra, "extra")
|
||||
}
|
||||
if r.ModTime.Unix() != 1e8 {
|
||||
t.Fatalf("mtime is %d, want %d", r.ModTime.Unix(), uint32(1e8))
|
||||
}
|
||||
if r.Name != "name" {
|
||||
t.Fatalf("name is %q, want %q", r.Name, "name")
|
||||
}
|
||||
if err := r.Close(); err != nil {
|
||||
t.Fatalf("Reader.Close: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLatin1 tests the internal functions for converting to and from Latin-1.
|
||||
func TestLatin1(t *testing.T) {
|
||||
latin1 := []byte{0xc4, 'u', 0xdf, 'e', 'r', 'u', 'n', 'g', 0}
|
||||
utf8 := "Äußerung"
|
||||
z := Decompressor{r: bufio.NewReader(bytes.NewBuffer(latin1))}
|
||||
z := Reader{r: bufio.NewReader(bytes.NewBuffer(latin1))}
|
||||
s, err := z.readString()
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
t.Fatalf("readString: %v", err)
|
||||
}
|
||||
if s != utf8 {
|
||||
t.Fatalf("string is %q, want %q", s, utf8)
|
||||
t.Fatalf("read latin-1: got %q, want %q", s, utf8)
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(make([]byte, 0, len(latin1)))
|
||||
c := Compressor{w: buf}
|
||||
c := Writer{w: buf}
|
||||
if err = c.writeString(utf8); err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
t.Fatalf("writeString: %v", err)
|
||||
}
|
||||
s = buf.String()
|
||||
if s != string(latin1) {
|
||||
t.Fatalf("string is %v, want %v", s, latin1)
|
||||
t.Fatalf("write utf-8: got %q, want %q", s, string(latin1))
|
||||
}
|
||||
}
|
||||
|
||||
// TestLatin1RoundTrip tests that metadata that is representable in Latin-1
|
||||
// survives a round trip.
|
||||
func TestLatin1RoundTrip(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
ok bool
|
||||
}{
|
||||
{"", true},
|
||||
{"ASCII is OK", true},
|
||||
{"unless it contains a NUL\x00", false},
|
||||
{"no matter where \x00 occurs", false},
|
||||
{"\x00\x00\x00", false},
|
||||
{"Látin-1 also passes (U+00E1)", true},
|
||||
{"but LĀtin Extended-A (U+0100) does not", false},
|
||||
{"neither does 日本語", false},
|
||||
{"invalid UTF-8 also \xffails", false},
|
||||
{"\x00 as does Látin-1 with NUL", false},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
w := NewWriter(buf)
|
||||
w.Name = tc.name
|
||||
err := w.Close()
|
||||
if (err == nil) != tc.ok {
|
||||
t.Errorf("Writer.Close: name = %q, err = %v", tc.name, err)
|
||||
continue
|
||||
}
|
||||
if !tc.ok {
|
||||
continue
|
||||
}
|
||||
|
||||
r, err := NewReader(buf)
|
||||
if err != nil {
|
||||
t.Errorf("NewReader: %v", err)
|
||||
continue
|
||||
}
|
||||
_, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Errorf("ReadAll: %v", err)
|
||||
continue
|
||||
}
|
||||
if r.Name != tc.name {
|
||||
t.Errorf("name is %q, want %q", r.Name, tc.name)
|
||||
continue
|
||||
}
|
||||
if err := r.Close(); err != nil {
|
||||
t.Errorf("Reader.Close: %v", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
//if s, err = buf.ReadString(0); err != nil {
|
||||
//t.Fatalf("%v", err)
|
||||
//}
|
||||
}
|
||||
|
|
|
@ -34,9 +34,14 @@ import (
|
|||
|
||||
const zlibDeflate = 8
|
||||
|
||||
var ErrChecksum = errors.New("zlib checksum error")
|
||||
var ErrHeader = errors.New("invalid zlib header")
|
||||
var ErrDictionary = errors.New("invalid zlib dictionary")
|
||||
var (
|
||||
// ErrChecksum is returned when reading ZLIB data that has an invalid checksum.
|
||||
ErrChecksum = errors.New("zlib: invalid checksum")
|
||||
// ErrDictionary is returned when reading ZLIB data that has an invalid dictionary.
|
||||
ErrDictionary = errors.New("zlib: invalid dictionary")
|
||||
// ErrHeader is returned when reading ZLIB data that has an invalid header.
|
||||
ErrHeader = errors.New("zlib: invalid header")
|
||||
)
|
||||
|
||||
type reader struct {
|
||||
r flate.Reader
|
||||
|
|
|
@ -6,7 +6,7 @@ package zlib
|
|||
|
||||
import (
|
||||
"compress/flate"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"hash/adler32"
|
||||
"io"
|
||||
|
@ -24,30 +24,55 @@ const (
|
|||
// A Writer takes data written to it and writes the compressed
|
||||
// form of that data to an underlying writer (see NewWriter).
|
||||
type Writer struct {
|
||||
w io.Writer
|
||||
compressor *flate.Writer
|
||||
digest hash.Hash32
|
||||
err error
|
||||
scratch [4]byte
|
||||
w io.Writer
|
||||
level int
|
||||
dict []byte
|
||||
compressor *flate.Writer
|
||||
digest hash.Hash32
|
||||
err error
|
||||
scratch [4]byte
|
||||
wroteHeader bool
|
||||
}
|
||||
|
||||
// NewWriter calls NewWriterLevel with the default compression level.
|
||||
func NewWriter(w io.Writer) (*Writer, error) {
|
||||
return NewWriterLevel(w, DefaultCompression)
|
||||
}
|
||||
|
||||
// NewWriterLevel calls NewWriterDict with no dictionary.
|
||||
func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
|
||||
return NewWriterDict(w, level, nil)
|
||||
}
|
||||
|
||||
// NewWriterDict creates a new io.WriteCloser that satisfies writes by compressing data written to w.
|
||||
// NewWriter creates a new Writer that satisfies writes by compressing data
|
||||
// written to w.
|
||||
//
|
||||
// It is the caller's responsibility to call Close on the WriteCloser when done.
|
||||
// level is the compression level, which can be DefaultCompression, NoCompression,
|
||||
// or any integer value between BestSpeed and BestCompression (inclusive).
|
||||
// dict is the preset dictionary to compress with, or nil to use no dictionary.
|
||||
func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) {
|
||||
z := new(Writer)
|
||||
// Writes may be buffered and not flushed until Close.
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
z, _ := NewWriterLevelDict(w, DefaultCompression, nil)
|
||||
return z
|
||||
}
|
||||
|
||||
// NewWriterLevel is like NewWriter but specifies the compression level instead
|
||||
// of assuming DefaultCompression.
|
||||
//
|
||||
// The compression level can be DefaultCompression, NoCompression, or any
|
||||
// integer value between BestSpeed and BestCompression inclusive. The error
|
||||
// returned will be nil if the level is valid.
|
||||
func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
|
||||
return NewWriterLevelDict(w, level, nil)
|
||||
}
|
||||
|
||||
// NewWriterLevelDict is like NewWriterLevel but specifies a dictionary to
|
||||
// compress with.
|
||||
//
|
||||
// The dictionary may be nil. If not, its contents should not be modified until
|
||||
// the Writer is closed.
|
||||
func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error) {
|
||||
if level < DefaultCompression || level > BestCompression {
|
||||
return nil, fmt.Errorf("zlib: invalid compression level: %d", level)
|
||||
}
|
||||
return &Writer{
|
||||
w: w,
|
||||
level: level,
|
||||
dict: dict,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// writeHeader writes the ZLIB header.
|
||||
func (z *Writer) writeHeader() (err error) {
|
||||
z.wroteHeader = true
|
||||
// ZLIB has a two-byte header (as documented in RFC 1950).
|
||||
// The first four bits is the CINFO (compression info), which is 7 for the default deflate window size.
|
||||
// The next four bits is the CM (compression method), which is 8 for deflate.
|
||||
|
@ -56,7 +81,7 @@ func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) {
|
|||
// 0=fastest, 1=fast, 2=default, 3=best.
|
||||
// The next bit, FDICT, is set if a dictionary is given.
|
||||
// The final five FCHECK bits form a mod-31 checksum.
|
||||
switch level {
|
||||
switch z.level {
|
||||
case 0, 1:
|
||||
z.scratch[1] = 0 << 6
|
||||
case 2, 3, 4, 5:
|
||||
|
@ -66,35 +91,41 @@ func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) {
|
|||
case 7, 8, 9:
|
||||
z.scratch[1] = 3 << 6
|
||||
default:
|
||||
return nil, errors.New("level out of range")
|
||||
panic("unreachable")
|
||||
}
|
||||
if dict != nil {
|
||||
if z.dict != nil {
|
||||
z.scratch[1] |= 1 << 5
|
||||
}
|
||||
z.scratch[1] += uint8(31 - (uint16(z.scratch[0])<<8+uint16(z.scratch[1]))%31)
|
||||
_, err := w.Write(z.scratch[0:2])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if _, err = z.w.Write(z.scratch[0:2]); err != nil {
|
||||
return err
|
||||
}
|
||||
if dict != nil {
|
||||
if z.dict != nil {
|
||||
// The next four bytes are the Adler-32 checksum of the dictionary.
|
||||
checksum := adler32.Checksum(dict)
|
||||
checksum := adler32.Checksum(z.dict)
|
||||
z.scratch[0] = uint8(checksum >> 24)
|
||||
z.scratch[1] = uint8(checksum >> 16)
|
||||
z.scratch[2] = uint8(checksum >> 8)
|
||||
z.scratch[3] = uint8(checksum >> 0)
|
||||
_, err = w.Write(z.scratch[0:4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if _, err = z.w.Write(z.scratch[0:4]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
z.w = w
|
||||
z.compressor = flate.NewWriterDict(w, level, dict)
|
||||
z.compressor, err = flate.NewWriterDict(z.w, z.level, z.dict)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
z.digest = adler32.New()
|
||||
return z, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write writes a compressed form of p to the underlying io.Writer. The
|
||||
// compressed bytes are not necessarily flushed until the Writer is closed or
|
||||
// explicitly flushed.
|
||||
func (z *Writer) Write(p []byte) (n int, err error) {
|
||||
if !z.wroteHeader {
|
||||
z.err = z.writeHeader()
|
||||
}
|
||||
if z.err != nil {
|
||||
return 0, z.err
|
||||
}
|
||||
|
@ -110,8 +141,11 @@ func (z *Writer) Write(p []byte) (n int, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// Flush flushes the underlying compressor.
|
||||
// Flush flushes the Writer to its underlying io.Writer.
|
||||
func (z *Writer) Flush() error {
|
||||
if !z.wroteHeader {
|
||||
z.err = z.writeHeader()
|
||||
}
|
||||
if z.err != nil {
|
||||
return z.err
|
||||
}
|
||||
|
@ -121,6 +155,9 @@ func (z *Writer) Flush() error {
|
|||
|
||||
// Calling Close does not close the wrapped io.Writer originally passed to NewWriter.
|
||||
func (z *Writer) Close() error {
|
||||
if !z.wroteHeader {
|
||||
z.err = z.writeHeader()
|
||||
}
|
||||
if z.err != nil {
|
||||
return z.err
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) {
|
|||
defer piper.Close()
|
||||
go func() {
|
||||
defer pipew.Close()
|
||||
zlibw, err := NewWriterDict(pipew, level, dict)
|
||||
zlibw, err := NewWriterLevelDict(pipew, level, dict)
|
||||
if err != nil {
|
||||
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
|
||||
return
|
||||
|
@ -125,9 +125,9 @@ func TestWriterDict(t *testing.T) {
|
|||
func TestWriterDictIsUsed(t *testing.T) {
|
||||
var input = []byte("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
|
||||
var buf bytes.Buffer
|
||||
compressor, err := NewWriterDict(&buf, BestCompression, input)
|
||||
compressor, err := NewWriterLevelDict(&buf, BestCompression, input)
|
||||
if err != nil {
|
||||
t.Errorf("error in NewWriterDict: %s", err)
|
||||
t.Errorf("error in NewWriterLevelDict: %s", err)
|
||||
return
|
||||
}
|
||||
compressor.Write(input)
|
||||
|
|
105
libgo/go/container/heap/example_test.go
Normal file
105
libgo/go/container/heap/example_test.go
Normal file
|
@ -0,0 +1,105 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This example demonstrates a priority queue built using the heap interface.
|
||||
package heap_test
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// An Item is something we manage in a priority queue.
|
||||
type Item struct {
|
||||
value string // The value of the item; arbitrary.
|
||||
priority int // The priority of the item in the queue.
|
||||
// The index is needed by changePriority and is maintained by the heap.Interface methods.
|
||||
index int // The index of the item in the heap.
|
||||
}
|
||||
|
||||
// A PriorityQueue implements heap.Interface and holds Items.
|
||||
type PriorityQueue []*Item
|
||||
|
||||
func (pq PriorityQueue) Len() int { return len(pq) }
|
||||
|
||||
func (pq PriorityQueue) Less(i, j int) bool {
|
||||
// We want Pop to give us the highest, not lowest, priority so we use greater than here.
|
||||
return pq[i].priority > pq[j].priority
|
||||
}
|
||||
|
||||
func (pq PriorityQueue) Swap(i, j int) {
|
||||
pq[i], pq[j] = pq[j], pq[i]
|
||||
pq[i].index = i
|
||||
pq[j].index = j
|
||||
}
|
||||
|
||||
func (pq *PriorityQueue) Push(x interface{}) {
|
||||
// Push and Pop use pointer receivers because they modify the slice's length,
|
||||
// not just its contents.
|
||||
// To simplify indexing expressions in these methods, we save a copy of the
|
||||
// slice object. We could instead write (*pq)[i].
|
||||
a := *pq
|
||||
n := len(a)
|
||||
a = a[0 : n+1]
|
||||
item := x.(*Item)
|
||||
item.index = n
|
||||
a[n] = item
|
||||
*pq = a
|
||||
}
|
||||
|
||||
func (pq *PriorityQueue) Pop() interface{} {
|
||||
a := *pq
|
||||
n := len(a)
|
||||
item := a[n-1]
|
||||
item.index = -1 // for safety
|
||||
*pq = a[0 : n-1]
|
||||
return item
|
||||
}
|
||||
|
||||
// 99:seven 88:five 77:zero 66:nine 55:three 44:two 33:six 22:one 11:four 00:eight
|
||||
func ExampleInterface() {
|
||||
// The full code of this example, including the methods that implement
|
||||
// heap.Interface, is in the file src/pkg/container/heap/example_test.go.
|
||||
|
||||
const nItem = 10
|
||||
// Random priorities for the items (a permutation of 0..9, times 11)).
|
||||
priorities := [nItem]int{
|
||||
77, 22, 44, 55, 11, 88, 33, 99, 00, 66,
|
||||
}
|
||||
values := [nItem]string{
|
||||
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||
}
|
||||
// Create a priority queue and put some items in it.
|
||||
pq := make(PriorityQueue, 0, nItem)
|
||||
for i := 0; i < cap(pq); i++ {
|
||||
item := &Item{
|
||||
value: values[i],
|
||||
priority: priorities[i],
|
||||
}
|
||||
heap.Push(&pq, item)
|
||||
}
|
||||
// Take the items out; should arrive in decreasing priority order.
|
||||
// For example, the highest priority (99) is the seventh item, so output starts with 99:"seven".
|
||||
for i := 0; i < nItem; i++ {
|
||||
item := heap.Pop(&pq).(*Item)
|
||||
fmt.Printf("%.2d:%s ", item.priority, item.value)
|
||||
}
|
||||
}
|
||||
|
||||
// update is not used by the example but shows how to take the top item from the queue,
|
||||
// update its priority and value, and put it back.
|
||||
func (pq *PriorityQueue) update(value string, priority int) {
|
||||
item := heap.Pop(pq).(*Item)
|
||||
item.value = value
|
||||
item.priority = priority
|
||||
heap.Push(pq, item)
|
||||
}
|
||||
|
||||
// changePriority is not used by the example but shows how to change the priority of an arbitrary
|
||||
// item.
|
||||
func (pq *PriorityQueue) changePriority(item *Item, priority int) {
|
||||
heap.Remove(pq, item.index)
|
||||
item.priority = priority
|
||||
heap.Push(pq, item)
|
||||
}
|
|
@ -6,10 +6,11 @@
|
|||
// heap.Interface. A heap is a tree with the property that each node is the
|
||||
// highest-valued node in its subtree.
|
||||
//
|
||||
// A heap is a common way to impement a priority queue. To build a priority
|
||||
// A heap is a common way to implement a priority queue. To build a priority
|
||||
// queue, implement the Heap interface with the (negative) priority as the
|
||||
// ordering for the Less method, so Push adds items while Pop removes the
|
||||
// highest-priority item from the queue.
|
||||
// highest-priority item from the queue. The Examples include such an
|
||||
// implementation; the file example_test.go has the complete source.
|
||||
//
|
||||
package heap
|
||||
|
||||
|
|
|
@ -4,13 +4,16 @@
|
|||
|
||||
package aes
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// The AES block size in bytes.
|
||||
const BlockSize = 16
|
||||
|
||||
// A Cipher is an instance of AES encryption using a particular key.
|
||||
type Cipher struct {
|
||||
// A cipher is an instance of AES encryption using a particular key.
|
||||
type aesCipher struct {
|
||||
enc []uint32
|
||||
dec []uint32
|
||||
}
|
||||
|
@ -21,11 +24,11 @@ func (k KeySizeError) Error() string {
|
|||
return "crypto/aes: invalid key size " + strconv.Itoa(int(k))
|
||||
}
|
||||
|
||||
// NewCipher creates and returns a new Cipher.
|
||||
// NewCipher creates and returns a new cipher.Block.
|
||||
// The key argument should be the AES key,
|
||||
// either 16, 24, or 32 bytes to select
|
||||
// AES-128, AES-192, or AES-256.
|
||||
func NewCipher(key []byte) (*Cipher, error) {
|
||||
func NewCipher(key []byte) (cipher.Block, error) {
|
||||
k := len(key)
|
||||
switch k {
|
||||
default:
|
||||
|
@ -35,34 +38,13 @@ func NewCipher(key []byte) (*Cipher, error) {
|
|||
}
|
||||
|
||||
n := k + 28
|
||||
c := &Cipher{make([]uint32, n), make([]uint32, n)}
|
||||
c := &aesCipher{make([]uint32, n), make([]uint32, n)}
|
||||
expandKey(key, c.enc, c.dec)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// BlockSize returns the AES block size, 16 bytes.
|
||||
// It is necessary to satisfy the Block interface in the
|
||||
// package "crypto/cipher".
|
||||
func (c *Cipher) BlockSize() int { return BlockSize }
|
||||
func (c *aesCipher) BlockSize() int { return BlockSize }
|
||||
|
||||
// Encrypt encrypts the 16-byte buffer src using the key k
|
||||
// and stores the result in dst.
|
||||
// Note that for amounts of data larger than a block,
|
||||
// it is not safe to just call Encrypt on successive blocks;
|
||||
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
|
||||
func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c.enc, dst, src) }
|
||||
func (c *aesCipher) Encrypt(dst, src []byte) { encryptBlock(c.enc, dst, src) }
|
||||
|
||||
// Decrypt decrypts the 16-byte buffer src using the key k
|
||||
// and stores the result in dst.
|
||||
func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c.dec, dst, src) }
|
||||
|
||||
// Reset zeros the key data, so that it will no longer
|
||||
// appear in the process's memory.
|
||||
func (c *Cipher) Reset() {
|
||||
for i := 0; i < len(c.enc); i++ {
|
||||
c.enc[i] = 0
|
||||
}
|
||||
for i := 0; i < len(c.dec); i++ {
|
||||
c.dec[i] = 0
|
||||
}
|
||||
}
|
||||
func (c *aesCipher) Decrypt(dst, src []byte) { decryptBlock(c.dec, dst, src) }
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
// Special Publication 800-38A, ``Recommendation for Block Cipher
|
||||
// Modes of Operation,'' 2001 Edition, pp. 24-29.
|
||||
|
||||
package cipher
|
||||
package cipher_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -72,14 +73,14 @@ func TestCBC_AES(t *testing.T) {
|
|||
continue
|
||||
}
|
||||
|
||||
encrypter := NewCBCEncrypter(c, tt.iv)
|
||||
encrypter := cipher.NewCBCEncrypter(c, tt.iv)
|
||||
d := make([]byte, len(tt.in))
|
||||
encrypter.CryptBlocks(d, tt.in)
|
||||
if !bytes.Equal(tt.out, d) {
|
||||
t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test, d, tt.out)
|
||||
}
|
||||
|
||||
decrypter := NewCBCDecrypter(c, tt.iv)
|
||||
decrypter := cipher.NewCBCDecrypter(c, tt.iv)
|
||||
p := make([]byte, len(d))
|
||||
decrypter.CryptBlocks(p, d)
|
||||
if !bytes.Equal(tt.in, p) {
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cipher
|
||||
package cipher_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
)
|
||||
|
@ -21,11 +22,11 @@ func TestCFB(t *testing.T) {
|
|||
plaintext := []byte("this is the plaintext")
|
||||
iv := make([]byte, block.BlockSize())
|
||||
rand.Reader.Read(iv)
|
||||
cfb := NewCFBEncrypter(block, iv)
|
||||
cfb := cipher.NewCFBEncrypter(block, iv)
|
||||
ciphertext := make([]byte, len(plaintext))
|
||||
cfb.XORKeyStream(ciphertext, plaintext)
|
||||
|
||||
cfbdec := NewCFBDecrypter(block, iv)
|
||||
cfbdec := cipher.NewCFBDecrypter(block, iv)
|
||||
plaintextCopy := make([]byte, len(plaintext))
|
||||
cfbdec.XORKeyStream(plaintextCopy, ciphertext)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cipher
|
||||
package cipher_test
|
||||
|
||||
// Common values for tests.
|
||||
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
// Special Publication 800-38A, ``Recommendation for Block Cipher
|
||||
// Modes of Operation,'' 2001 Edition, pp. 55-58.
|
||||
|
||||
package cipher
|
||||
package cipher_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -76,7 +77,7 @@ func TestCTR_AES(t *testing.T) {
|
|||
|
||||
for j := 0; j <= 5; j += 5 {
|
||||
in := tt.in[0 : len(tt.in)-j]
|
||||
ctr := NewCTR(c, tt.iv)
|
||||
ctr := cipher.NewCTR(c, tt.iv)
|
||||
encrypted := make([]byte, len(in))
|
||||
ctr.XORKeyStream(encrypted, in)
|
||||
if out := tt.out[0:len(in)]; !bytes.Equal(out, encrypted) {
|
||||
|
@ -86,7 +87,7 @@ func TestCTR_AES(t *testing.T) {
|
|||
|
||||
for j := 0; j <= 7; j += 7 {
|
||||
in := tt.out[0 : len(tt.out)-j]
|
||||
ctr := NewCTR(c, tt.iv)
|
||||
ctr := cipher.NewCTR(c, tt.iv)
|
||||
plain := make([]byte, len(in))
|
||||
ctr.XORKeyStream(plain, in)
|
||||
if out := tt.in[0:len(in)]; !bytes.Equal(out, plain) {
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
// Special Publication 800-38A, ``Recommendation for Block Cipher
|
||||
// Modes of Operation,'' 2001 Edition, pp. 52-55.
|
||||
|
||||
package cipher
|
||||
package cipher_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -76,7 +77,7 @@ func TestOFB(t *testing.T) {
|
|||
|
||||
for j := 0; j <= 5; j += 5 {
|
||||
plaintext := tt.in[0 : len(tt.in)-j]
|
||||
ofb := NewOFB(c, tt.iv)
|
||||
ofb := cipher.NewOFB(c, tt.iv)
|
||||
ciphertext := make([]byte, len(plaintext))
|
||||
ofb.XORKeyStream(ciphertext, plaintext)
|
||||
if !bytes.Equal(ciphertext, tt.out[:len(plaintext)]) {
|
||||
|
@ -86,7 +87,7 @@ func TestOFB(t *testing.T) {
|
|||
|
||||
for j := 0; j <= 5; j += 5 {
|
||||
ciphertext := tt.out[0 : len(tt.in)-j]
|
||||
ofb := NewOFB(c, tt.iv)
|
||||
ofb := cipher.NewOFB(c, tt.iv)
|
||||
plaintext := make([]byte, len(ciphertext))
|
||||
ofb.XORKeyStream(plaintext, ciphertext)
|
||||
if !bytes.Equal(plaintext, tt.in[:len(ciphertext)]) {
|
||||
|
|
|
@ -79,7 +79,7 @@ func ksRotate(in uint32) (out []uint32) {
|
|||
}
|
||||
|
||||
// creates 16 56-bit subkeys from the original key
|
||||
func (c *Cipher) generateSubkeys(keyBytes []byte) {
|
||||
func (c *desCipher) generateSubkeys(keyBytes []byte) {
|
||||
// apply PC1 permutation to key
|
||||
key := binary.BigEndian.Uint64(keyBytes)
|
||||
permutedKey := permuteBlock(key, permutedChoice1[:])
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
package des
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// The DES block size in bytes.
|
||||
const BlockSize = 8
|
||||
|
@ -15,86 +18,56 @@ func (k KeySizeError) Error() string {
|
|||
return "crypto/des: invalid key size " + strconv.Itoa(int(k))
|
||||
}
|
||||
|
||||
// Cipher is an instance of DES encryption.
|
||||
type Cipher struct {
|
||||
// desCipher is an instance of DES encryption.
|
||||
type desCipher struct {
|
||||
subkeys [16]uint64
|
||||
}
|
||||
|
||||
// NewCipher creates and returns a new Cipher.
|
||||
func NewCipher(key []byte) (*Cipher, error) {
|
||||
// NewCipher creates and returns a new cipher.Block.
|
||||
func NewCipher(key []byte) (cipher.Block, error) {
|
||||
if len(key) != 8 {
|
||||
return nil, KeySizeError(len(key))
|
||||
}
|
||||
|
||||
c := new(Cipher)
|
||||
c := new(desCipher)
|
||||
c.generateSubkeys(key)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// BlockSize returns the DES block size, 8 bytes.
|
||||
func (c *Cipher) BlockSize() int { return BlockSize }
|
||||
func (c *desCipher) BlockSize() int { return BlockSize }
|
||||
|
||||
// Encrypt encrypts the 8-byte buffer src and stores the result in dst.
|
||||
// Note that for amounts of data larger than a block,
|
||||
// it is not safe to just call Encrypt on successive blocks;
|
||||
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
|
||||
func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
|
||||
func (c *desCipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
|
||||
|
||||
// Decrypt decrypts the 8-byte buffer src and stores the result in dst.
|
||||
func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
|
||||
func (c *desCipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
|
||||
|
||||
// Reset zeros the key data, so that it will no longer
|
||||
// appear in the process's memory.
|
||||
func (c *Cipher) Reset() {
|
||||
for i := 0; i < len(c.subkeys); i++ {
|
||||
c.subkeys[i] = 0
|
||||
}
|
||||
// A tripleDESCipher is an instance of TripleDES encryption.
|
||||
type tripleDESCipher struct {
|
||||
cipher1, cipher2, cipher3 desCipher
|
||||
}
|
||||
|
||||
// A TripleDESCipher is an instance of TripleDES encryption.
|
||||
type TripleDESCipher struct {
|
||||
cipher1, cipher2, cipher3 Cipher
|
||||
}
|
||||
|
||||
// NewCipher creates and returns a new Cipher.
|
||||
func NewTripleDESCipher(key []byte) (*TripleDESCipher, error) {
|
||||
// NewTripleDESCipher creates and returns a new cipher.Block.
|
||||
func NewTripleDESCipher(key []byte) (cipher.Block, error) {
|
||||
if len(key) != 24 {
|
||||
return nil, KeySizeError(len(key))
|
||||
}
|
||||
|
||||
c := new(TripleDESCipher)
|
||||
c := new(tripleDESCipher)
|
||||
c.cipher1.generateSubkeys(key[:8])
|
||||
c.cipher2.generateSubkeys(key[8:16])
|
||||
c.cipher3.generateSubkeys(key[16:])
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// BlockSize returns the TripleDES block size, 8 bytes.
|
||||
// It is necessary to satisfy the Block interface in the
|
||||
// package "crypto/cipher".
|
||||
func (c *TripleDESCipher) BlockSize() int { return BlockSize }
|
||||
func (c *tripleDESCipher) BlockSize() int { return BlockSize }
|
||||
|
||||
// Encrypts the 8-byte buffer src and stores the result in dst.
|
||||
// Note that for amounts of data larger than a block,
|
||||
// it is not safe to just call Encrypt on successive blocks;
|
||||
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
|
||||
func (c *TripleDESCipher) Encrypt(dst, src []byte) {
|
||||
func (c *tripleDESCipher) Encrypt(dst, src []byte) {
|
||||
c.cipher1.Encrypt(dst, src)
|
||||
c.cipher2.Decrypt(dst, dst)
|
||||
c.cipher3.Encrypt(dst, dst)
|
||||
}
|
||||
|
||||
// Decrypts the 8-byte buffer src and stores the result in dst.
|
||||
func (c *TripleDESCipher) Decrypt(dst, src []byte) {
|
||||
func (c *tripleDESCipher) Decrypt(dst, src []byte) {
|
||||
c.cipher3.Decrypt(dst, src)
|
||||
c.cipher2.Encrypt(dst, dst)
|
||||
c.cipher1.Decrypt(dst, dst)
|
||||
}
|
||||
|
||||
// Reset zeros the key data, so that it will no longer
|
||||
// appear in the process's memory.
|
||||
func (c *TripleDESCipher) Reset() {
|
||||
c.cipher1.Reset()
|
||||
c.cipher2.Reset()
|
||||
c.cipher3.Reset()
|
||||
}
|
||||
|
|
|
@ -1260,11 +1260,19 @@ var tableA4Tests = []CryptTest{
|
|||
[]byte{0x63, 0xfa, 0xc0, 0xd0, 0x34, 0xd9, 0xf7, 0x93}},
|
||||
}
|
||||
|
||||
func newCipher(key []byte) *desCipher {
|
||||
c, err := NewCipher(key)
|
||||
if err != nil {
|
||||
panic("NewCipher failed: " + err.Error())
|
||||
}
|
||||
return c.(*desCipher)
|
||||
}
|
||||
|
||||
// Use the known weak keys to test DES implementation
|
||||
func TestWeakKeys(t *testing.T) {
|
||||
for i, tt := range weakKeyTests {
|
||||
var encrypt = func(in []byte) (out []byte) {
|
||||
c, _ := NewCipher(tt.key)
|
||||
c := newCipher(tt.key)
|
||||
out = make([]byte, len(in))
|
||||
encryptBlock(c.subkeys[:], out, in)
|
||||
return
|
||||
|
@ -1285,7 +1293,7 @@ func TestWeakKeys(t *testing.T) {
|
|||
func TestSemiWeakKeyPairs(t *testing.T) {
|
||||
for i, tt := range semiWeakKeyTests {
|
||||
var encrypt = func(key, in []byte) (out []byte) {
|
||||
c, _ := NewCipher(key)
|
||||
c := newCipher(key)
|
||||
out = make([]byte, len(in))
|
||||
encryptBlock(c.subkeys[:], out, in)
|
||||
return
|
||||
|
@ -1305,7 +1313,7 @@ func TestSemiWeakKeyPairs(t *testing.T) {
|
|||
|
||||
func TestDESEncryptBlock(t *testing.T) {
|
||||
for i, tt := range encryptDESTests {
|
||||
c, _ := NewCipher(tt.key)
|
||||
c := newCipher(tt.key)
|
||||
out := make([]byte, len(tt.in))
|
||||
encryptBlock(c.subkeys[:], out, tt.in)
|
||||
|
||||
|
@ -1317,7 +1325,7 @@ func TestDESEncryptBlock(t *testing.T) {
|
|||
|
||||
func TestDESDecryptBlock(t *testing.T) {
|
||||
for i, tt := range encryptDESTests {
|
||||
c, _ := NewCipher(tt.key)
|
||||
c := newCipher(tt.key)
|
||||
plain := make([]byte, len(tt.in))
|
||||
decryptBlock(c.subkeys[:], plain, tt.out)
|
||||
|
||||
|
|
|
@ -29,17 +29,11 @@ type PrivateKey struct {
|
|||
X *big.Int
|
||||
}
|
||||
|
||||
type invalidPublicKeyError int
|
||||
|
||||
func (invalidPublicKeyError) Error() string {
|
||||
return "crypto/dsa: invalid public key"
|
||||
}
|
||||
|
||||
// ErrInvalidPublicKey results when a public key is not usable by this code.
|
||||
// FIPS is quite strict about the format of DSA keys, but other code may be
|
||||
// less so. Thus, when using keys which may have been generated by other code,
|
||||
// this error must be handled.
|
||||
var ErrInvalidPublicKey error = invalidPublicKeyError(0)
|
||||
var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key")
|
||||
|
||||
// ParameterSizes is a enumeration of the acceptable bit lengths of the primes
|
||||
// in a set of DSA parameters. See FIPS 186-3, section 4.2.
|
||||
|
|
|
@ -22,7 +22,7 @@ func TestRead(t *testing.T) {
|
|||
}
|
||||
|
||||
var z bytes.Buffer
|
||||
f := flate.NewWriter(&z, 5)
|
||||
f, _ := flate.NewWriter(&z, 5)
|
||||
f.Write(b)
|
||||
f.Close()
|
||||
if z.Len() < len(b)*99/100 {
|
||||
|
|
|
@ -12,6 +12,7 @@ package rand
|
|||
import (
|
||||
"bufio"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
|
@ -66,7 +67,7 @@ func newReader(entropy io.Reader) io.Reader {
|
|||
type reader struct {
|
||||
mu sync.Mutex
|
||||
budget int // number of bytes that can be generated
|
||||
cipher *aes.Cipher
|
||||
cipher cipher.Block
|
||||
entropy io.Reader
|
||||
time, seed, dst, key [aes.BlockSize]byte
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) {
|
||||
k := (pub.N.BitLen() + 7) / 8
|
||||
if len(msg) > k-11 {
|
||||
err = MessageTooLongError{}
|
||||
err = ErrMessageTooLong
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
|
|||
func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) {
|
||||
valid, out, err := decryptPKCS1v15(rand, priv, ciphertext)
|
||||
if err == nil && valid == 0 {
|
||||
err = DecryptionError{}
|
||||
err = ErrDecryption
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -69,7 +69,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [
|
|||
func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
|
||||
k := (priv.N.BitLen() + 7) / 8
|
||||
if k-(len(key)+3+8) < 0 {
|
||||
err = DecryptionError{}
|
||||
err = ErrDecryption
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by
|
|||
func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, msg []byte, err error) {
|
||||
k := (priv.N.BitLen() + 7) / 8
|
||||
if k < 11 {
|
||||
err = DecryptionError{}
|
||||
err = ErrDecryption
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
|
|||
tLen := len(prefix) + hashLen
|
||||
k := (priv.N.BitLen() + 7) / 8
|
||||
if k < tLen+11 {
|
||||
return nil, MessageTooLongError{}
|
||||
return nil, ErrMessageTooLong
|
||||
}
|
||||
|
||||
// EM = 0x00 || 0x01 || PS || 0x00 || T
|
||||
|
@ -203,7 +203,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
|
|||
tLen := len(prefix) + hashLen
|
||||
k := (pub.N.BitLen() + 7) / 8
|
||||
if k < tLen+11 {
|
||||
err = VerificationError{}
|
||||
err = ErrVerification
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
|
|||
}
|
||||
|
||||
if ok != 1 {
|
||||
return VerificationError{}
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -206,13 +206,9 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
|
|||
}
|
||||
}
|
||||
|
||||
// MessageTooLongError is returned when attempting to encrypt a message which
|
||||
// is too large for the size of the public key.
|
||||
type MessageTooLongError struct{}
|
||||
|
||||
func (MessageTooLongError) Error() string {
|
||||
return "message too long for RSA public key size"
|
||||
}
|
||||
// ErrMessageTooLong is returned when attempting to encrypt a message which is
|
||||
// too large for the size of the public key.
|
||||
var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size")
|
||||
|
||||
func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
|
||||
e := big.NewInt(int64(pub.E))
|
||||
|
@ -227,7 +223,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
|
|||
hash.Reset()
|
||||
k := (pub.N.BitLen() + 7) / 8
|
||||
if len(msg) > k-2*hash.Size()-2 {
|
||||
err = MessageTooLongError{}
|
||||
err = ErrMessageTooLong
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -266,17 +262,13 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
|
|||
return
|
||||
}
|
||||
|
||||
// A DecryptionError represents a failure to decrypt a message.
|
||||
// ErrDecryption represents a failure to decrypt a message.
|
||||
// It is deliberately vague to avoid adaptive attacks.
|
||||
type DecryptionError struct{}
|
||||
var ErrDecryption = errors.New("crypto/rsa: decryption error")
|
||||
|
||||
func (DecryptionError) Error() string { return "RSA decryption error" }
|
||||
|
||||
// A VerificationError represents a failure to verify a signature.
|
||||
// ErrVerification represents a failure to verify a signature.
|
||||
// It is deliberately vague to avoid adaptive attacks.
|
||||
type VerificationError struct{}
|
||||
|
||||
func (VerificationError) Error() string { return "RSA verification error" }
|
||||
var ErrVerification = errors.New("crypto/rsa: verification error")
|
||||
|
||||
// modInverse returns ia, the inverse of a in the multiplicative group of prime
|
||||
// order n. It requires that a be a member of the group (i.e. less than n).
|
||||
|
@ -338,7 +330,7 @@ func (priv *PrivateKey) Precompute() {
|
|||
func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
|
||||
// TODO(agl): can we get away with reusing blinds?
|
||||
if c.Cmp(priv.N) > 0 {
|
||||
err = DecryptionError{}
|
||||
err = ErrDecryption
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -417,7 +409,7 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
|
|||
k := (priv.N.BitLen() + 7) / 8
|
||||
if len(ciphertext) > k ||
|
||||
k < hash.Size()*2+2 {
|
||||
err = DecryptionError{}
|
||||
err = ErrDecryption
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -473,7 +465,7 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
|
|||
}
|
||||
|
||||
if firstByteIsZero&lHash2Good&^invalid&^lookingForIndex != 1 {
|
||||
err = DecryptionError{}
|
||||
err = ErrDecryption
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -87,9 +87,9 @@ func (c *Conn) RemoteAddr() net.Addr {
|
|||
return c.conn.RemoteAddr()
|
||||
}
|
||||
|
||||
// SetDeadline sets the read deadline associated with the connection.
|
||||
// There is no write deadline.
|
||||
// A zero value for t means Read will not time out.
|
||||
// SetDeadline sets the read and write deadlines associated with the connection.
|
||||
// A zero value for t means Read and Write will not time out.
|
||||
// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
|
||||
func (c *Conn) SetDeadline(t time.Time) error {
|
||||
return c.conn.SetDeadline(t)
|
||||
}
|
||||
|
@ -100,10 +100,11 @@ func (c *Conn) SetReadDeadline(t time.Time) error {
|
|||
return c.conn.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// SetWriteDeadline exists to satisfy the net.Conn interface
|
||||
// but is not implemented by TLS. It always returns an error.
|
||||
// SetWriteDeadline sets the write deadline on the underlying conneciton.
|
||||
// A zero value for t means Write will not time out.
|
||||
// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
|
||||
func (c *Conn) SetWriteDeadline(t time.Time) error {
|
||||
return errors.New("TLS does not support SetWriteDeadline")
|
||||
return c.conn.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
// A halfConn represents one direction of the record layer
|
||||
|
@ -726,9 +727,13 @@ func (c *Conn) readHandshake() (interface{}, error) {
|
|||
}
|
||||
|
||||
// Write writes data to the connection.
|
||||
func (c *Conn) Write(b []byte) (n int, err error) {
|
||||
if err = c.Handshake(); err != nil {
|
||||
return
|
||||
func (c *Conn) Write(b []byte) (int, error) {
|
||||
if c.err != nil {
|
||||
return 0, c.err
|
||||
}
|
||||
|
||||
if c.err = c.Handshake(); c.err != nil {
|
||||
return 0, c.err
|
||||
}
|
||||
|
||||
c.out.Lock()
|
||||
|
@ -737,10 +742,10 @@ func (c *Conn) Write(b []byte) (n int, err error) {
|
|||
if !c.handshakeComplete {
|
||||
return 0, alertInternalError
|
||||
}
|
||||
if c.err != nil {
|
||||
return 0, c.err
|
||||
}
|
||||
return c.writeRecord(recordTypeApplicationData, b)
|
||||
|
||||
var n int
|
||||
n, c.err = c.writeRecord(recordTypeApplicationData, b)
|
||||
return n, c.err
|
||||
}
|
||||
|
||||
// Read can be made to time out and return a net.Error with Timeout() == true
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generate a self-signed X.509 certificate for a TLS server. Outputs to
|
||||
// 'cert.pem' and 'key.pem' and will overwrite existing files.
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ func TestRunClient(t *testing.T) {
|
|||
|
||||
// Script of interaction with gnutls implementation.
|
||||
// The values for this test are obtained by building and running in client mode:
|
||||
// % gotest -test.run "TestRunClient" -connect
|
||||
// % go test -run "TestRunClient" -connect
|
||||
// and then:
|
||||
// % gnutls-serv -p 10443 --debug 100 --x509keyfile key.pem --x509certfile cert.pem -a > /tmp/log 2>&1
|
||||
// % python parse-gnutls-cli-debug-log.py < /tmp/log
|
||||
|
|
|
@ -284,7 +284,7 @@ func loadPEMCert(in string) *x509.Certificate {
|
|||
|
||||
// Script of interaction with gnutls implementation.
|
||||
// The values for this test are obtained by building and running in server mode:
|
||||
// % gotest -test.run "TestRunServer" -serve
|
||||
// % go test -run "TestRunServer" -serve
|
||||
// and then:
|
||||
// % gnutls-cli --insecure --debug 100 -p 10443 localhost > /tmp/log 2>&1
|
||||
// % python parse-gnutls-cli-debug-log.py < /tmp/log
|
||||
|
@ -949,7 +949,7 @@ var sslv3ServerScript = [][]byte{
|
|||
|
||||
var clientauthTests = []clientauthTest{
|
||||
// Server doesn't asks for cert
|
||||
// gotest -test.run "TestRunServer" -serve -clientauth 0
|
||||
// go test -run "TestRunServer" -serve -clientauth 0
|
||||
// gnutls-cli --insecure --debug 100 -p 10443 localhost 2>&1 |
|
||||
// python parse-gnutls-cli-debug-log.py
|
||||
{"NoClientCert", NoClientCert, nil,
|
||||
|
@ -1115,7 +1115,7 @@ var clientauthTests = []clientauthTest{
|
|||
0x03, 0x11, 0x43, 0x3e, 0xee, 0xb7, 0x4d, 0x69,
|
||||
}}},
|
||||
// Server asks for cert with empty CA list, client doesn't give it.
|
||||
// gotest -test.run "TestRunServer" -serve -clientauth 1
|
||||
// go test -run "TestRunServer" -serve -clientauth 1
|
||||
// gnutls-cli --insecure --debug 100 -p 10443 localhost
|
||||
{"RequestClientCert, none given", RequestClientCert, nil,
|
||||
[][]byte{{
|
||||
|
@ -1282,7 +1282,7 @@ var clientauthTests = []clientauthTest{
|
|||
0xf4, 0x70, 0xcc, 0xb4, 0xed, 0x07, 0x76, 0x3a,
|
||||
}}},
|
||||
// Server asks for cert with empty CA list, client gives one
|
||||
// gotest -test.run "TestRunServer" -serve -clientauth 1
|
||||
// go test -run "TestRunServer" -serve -clientauth 1
|
||||
// gnutls-cli --insecure --debug 100 -p 10443 localhost
|
||||
{"RequestClientCert, client gives it", RequestClientCert,
|
||||
[]*x509.Certificate{clicert},
|
||||
|
|
|
@ -327,13 +327,9 @@ type Certificate struct {
|
|||
PolicyIdentifiers []asn1.ObjectIdentifier
|
||||
}
|
||||
|
||||
// UnsupportedAlgorithmError results from attempting to perform an operation
|
||||
// that involves algorithms that are not currently implemented.
|
||||
type UnsupportedAlgorithmError struct{}
|
||||
|
||||
func (UnsupportedAlgorithmError) Error() string {
|
||||
return "cannot verify signature: algorithm unimplemented"
|
||||
}
|
||||
// ErrUnsupportedAlgorithm results from attempting to perform an operation that
|
||||
// involves algorithms that are not currently implemented.
|
||||
var ErrUnsupportedAlgorithm = errors.New("crypto/x509: cannot verify signature: algorithm unimplemented")
|
||||
|
||||
// ConstraintViolationError results when a requested usage is not permitted by
|
||||
// a certificate. For example: checking a signature when the public key isn't a
|
||||
|
@ -341,7 +337,7 @@ func (UnsupportedAlgorithmError) Error() string {
|
|||
type ConstraintViolationError struct{}
|
||||
|
||||
func (ConstraintViolationError) Error() string {
|
||||
return "invalid signature: parent certificate cannot sign this kind of certificate"
|
||||
return "crypto/x509: invalid signature: parent certificate cannot sign this kind of certificate"
|
||||
}
|
||||
|
||||
func (c *Certificate) Equal(other *Certificate) bool {
|
||||
|
@ -366,7 +362,7 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) {
|
|||
}
|
||||
|
||||
if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm {
|
||||
return UnsupportedAlgorithmError{}
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
// TODO(agl): don't ignore the path length constraint.
|
||||
|
@ -389,12 +385,12 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
|
|||
case SHA512WithRSA:
|
||||
hashType = crypto.SHA512
|
||||
default:
|
||||
return UnsupportedAlgorithmError{}
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
h := hashType.New()
|
||||
if h == nil {
|
||||
return UnsupportedAlgorithmError{}
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
h.Write(signed)
|
||||
|
@ -416,7 +412,7 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
|
|||
}
|
||||
return
|
||||
}
|
||||
return UnsupportedAlgorithmError{}
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
// CheckCRLSignature checks that the signature in crl is from c.
|
||||
|
@ -795,7 +791,7 @@ var (
|
|||
)
|
||||
|
||||
func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
|
||||
ret = make([]pkix.Extension, 7 /* maximum number of elements. */ )
|
||||
ret = make([]pkix.Extension, 7 /* maximum number of elements. */)
|
||||
n := 0
|
||||
|
||||
if template.KeyUsage != 0 {
|
||||
|
|
|
@ -90,8 +90,8 @@ func convertAssign(dest, src interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if scanner, ok := dest.(ScannerInto); ok {
|
||||
return scanner.ScanInto(src)
|
||||
if scanner, ok := dest.(Scanner); ok {
|
||||
return scanner.Scan(src)
|
||||
}
|
||||
|
||||
dpv := reflect.ValueOf(dest)
|
||||
|
@ -110,6 +110,14 @@ func convertAssign(dest, src interface{}) error {
|
|||
}
|
||||
|
||||
switch dv.Kind() {
|
||||
case reflect.Ptr:
|
||||
if src == nil {
|
||||
dv.Set(reflect.Zero(dv.Type()))
|
||||
return nil
|
||||
} else {
|
||||
dv.Set(reflect.New(dv.Type().Elem()))
|
||||
return convertAssign(dv.Interface(), src)
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
s := asString(src)
|
||||
i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
)
|
||||
|
||||
var someTime = time.Unix(123, 0)
|
||||
var answer int64 = 42
|
||||
|
||||
type conversionTest struct {
|
||||
s, d interface{} // source and destination
|
||||
|
@ -27,6 +28,8 @@ type conversionTest struct {
|
|||
wantbool bool // used if d is of type *bool
|
||||
wanterr string
|
||||
wantiface interface{}
|
||||
wantptr *int64 // if non-nil, *d's pointed value must be equal to *wantptr
|
||||
wantnil bool // if true, *d must be *int64(nil)
|
||||
}
|
||||
|
||||
// Target variables for scanning into.
|
||||
|
@ -42,6 +45,7 @@ var (
|
|||
scanf32 float32
|
||||
scanf64 float64
|
||||
scantime time.Time
|
||||
scanptr *int64
|
||||
scaniface interface{}
|
||||
)
|
||||
|
||||
|
@ -98,6 +102,10 @@ var conversionTests = []conversionTest{
|
|||
{s: "1.5", d: &scanf32, wantf32: float32(1.5)},
|
||||
{s: "1.5", d: &scanf64, wantf64: float64(1.5)},
|
||||
|
||||
// Pointers
|
||||
{s: interface{}(nil), d: &scanptr, wantnil: true},
|
||||
{s: int64(42), d: &scanptr, wantptr: &answer},
|
||||
|
||||
// To interface{}
|
||||
{s: float64(1.5), d: &scaniface, wantiface: float64(1.5)},
|
||||
{s: int64(1), d: &scaniface, wantiface: int64(1)},
|
||||
|
@ -107,6 +115,10 @@ var conversionTests = []conversionTest{
|
|||
{s: nil, d: &scaniface},
|
||||
}
|
||||
|
||||
func intPtrValue(intptr interface{}) interface{} {
|
||||
return reflect.Indirect(reflect.Indirect(reflect.ValueOf(intptr))).Int()
|
||||
}
|
||||
|
||||
func intValue(intptr interface{}) int64 {
|
||||
return reflect.Indirect(reflect.ValueOf(intptr)).Int()
|
||||
}
|
||||
|
@ -162,6 +174,16 @@ func TestConversions(t *testing.T) {
|
|||
if !ct.wanttime.IsZero() && !ct.wanttime.Equal(timeValue(ct.d)) {
|
||||
errf("want time %v, got %v", ct.wanttime, timeValue(ct.d))
|
||||
}
|
||||
if ct.wantnil && *ct.d.(**int64) != nil {
|
||||
errf("want nil, got %v", intPtrValue(ct.d))
|
||||
}
|
||||
if ct.wantptr != nil {
|
||||
if *ct.d.(**int64) == nil {
|
||||
errf("want pointer to %v, got nil", *ct.wantptr)
|
||||
} else if *ct.wantptr != intPtrValue(ct.d) {
|
||||
errf("want pointer to %v, got %v", *ct.wantptr, intPtrValue(ct.d))
|
||||
}
|
||||
}
|
||||
if ifptr, ok := ct.d.(*interface{}); ok {
|
||||
if !reflect.DeepEqual(ct.wantiface, scaniface) {
|
||||
errf("want interface %#v, got %#v", ct.wantiface, scaniface)
|
||||
|
|
|
@ -248,6 +248,13 @@ func (defaultConverter) ConvertValue(v interface{}) (interface{}, error) {
|
|||
|
||||
rv := reflect.ValueOf(v)
|
||||
switch rv.Kind() {
|
||||
case reflect.Ptr:
|
||||
// indirect pointers
|
||||
if rv.IsNil() {
|
||||
return nil, nil
|
||||
} else {
|
||||
return defaultConverter{}.ConvertValue(rv.Elem().Interface())
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return rv.Int(), nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
|
||||
|
|
|
@ -18,6 +18,7 @@ type valueConverterTest struct {
|
|||
}
|
||||
|
||||
var now = time.Now()
|
||||
var answer int64 = 42
|
||||
|
||||
var valueConverterTests = []valueConverterTest{
|
||||
{Bool, "true", true, ""},
|
||||
|
@ -37,6 +38,9 @@ var valueConverterTests = []valueConverterTest{
|
|||
{c: Bool, in: "foo", err: "sql/driver: couldn't convert \"foo\" into type bool"},
|
||||
{c: Bool, in: 2, err: "sql/driver: couldn't convert 2 into type bool"},
|
||||
{DefaultParameterConverter, now, now, ""},
|
||||
{DefaultParameterConverter, (*int64)(nil), nil, ""},
|
||||
{DefaultParameterConverter, &answer, answer, ""},
|
||||
{DefaultParameterConverter, &now, now, ""},
|
||||
}
|
||||
|
||||
func TestValueConverters(t *testing.T) {
|
||||
|
|
|
@ -35,7 +35,7 @@ func Register(name string, driver driver.Driver) {
|
|||
type RawBytes []byte
|
||||
|
||||
// NullString represents a string that may be null.
|
||||
// NullString implements the ScannerInto interface so
|
||||
// NullString implements the Scanner interface so
|
||||
// it can be used as a scan destination:
|
||||
//
|
||||
// var s NullString
|
||||
|
@ -52,8 +52,8 @@ type NullString struct {
|
|||
Valid bool // Valid is true if String is not NULL
|
||||
}
|
||||
|
||||
// ScanInto implements the ScannerInto interface.
|
||||
func (ns *NullString) ScanInto(value interface{}) error {
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullString) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ns.String, ns.Valid = "", false
|
||||
return nil
|
||||
|
@ -71,15 +71,15 @@ func (ns NullString) SubsetValue() (interface{}, error) {
|
|||
}
|
||||
|
||||
// NullInt64 represents an int64 that may be null.
|
||||
// NullInt64 implements the ScannerInto interface so
|
||||
// NullInt64 implements the Scanner interface so
|
||||
// it can be used as a scan destination, similar to NullString.
|
||||
type NullInt64 struct {
|
||||
Int64 int64
|
||||
Valid bool // Valid is true if Int64 is not NULL
|
||||
}
|
||||
|
||||
// ScanInto implements the ScannerInto interface.
|
||||
func (n *NullInt64) ScanInto(value interface{}) error {
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullInt64) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
n.Int64, n.Valid = 0, false
|
||||
return nil
|
||||
|
@ -97,15 +97,15 @@ func (n NullInt64) SubsetValue() (interface{}, error) {
|
|||
}
|
||||
|
||||
// NullFloat64 represents a float64 that may be null.
|
||||
// NullFloat64 implements the ScannerInto interface so
|
||||
// NullFloat64 implements the Scanner interface so
|
||||
// it can be used as a scan destination, similar to NullString.
|
||||
type NullFloat64 struct {
|
||||
Float64 float64
|
||||
Valid bool // Valid is true if Float64 is not NULL
|
||||
}
|
||||
|
||||
// ScanInto implements the ScannerInto interface.
|
||||
func (n *NullFloat64) ScanInto(value interface{}) error {
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullFloat64) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
n.Float64, n.Valid = 0, false
|
||||
return nil
|
||||
|
@ -123,15 +123,15 @@ func (n NullFloat64) SubsetValue() (interface{}, error) {
|
|||
}
|
||||
|
||||
// NullBool represents a bool that may be null.
|
||||
// NullBool implements the ScannerInto interface so
|
||||
// NullBool implements the Scanner interface so
|
||||
// it can be used as a scan destination, similar to NullString.
|
||||
type NullBool struct {
|
||||
Bool bool
|
||||
Valid bool // Valid is true if Bool is not NULL
|
||||
}
|
||||
|
||||
// ScanInto implements the ScannerInto interface.
|
||||
func (n *NullBool) ScanInto(value interface{}) error {
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullBool) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
n.Bool, n.Valid = false, false
|
||||
return nil
|
||||
|
@ -148,22 +148,24 @@ func (n NullBool) SubsetValue() (interface{}, error) {
|
|||
return n.Bool, nil
|
||||
}
|
||||
|
||||
// ScannerInto is an interface used by Scan.
|
||||
type ScannerInto interface {
|
||||
// ScanInto assigns a value from a database driver.
|
||||
// Scanner is an interface used by Scan.
|
||||
type Scanner interface {
|
||||
// Scan assigns a value from a database driver.
|
||||
//
|
||||
// The value will be of one of the following restricted
|
||||
// The src value will be of one of the following restricted
|
||||
// set of types:
|
||||
//
|
||||
// int64
|
||||
// float64
|
||||
// bool
|
||||
// []byte
|
||||
// string
|
||||
// time.Time
|
||||
// nil - for NULL values
|
||||
//
|
||||
// An error should be returned if the value can not be stored
|
||||
// without loss of information.
|
||||
ScanInto(value interface{}) error
|
||||
Scan(src interface{}) error
|
||||
}
|
||||
|
||||
// ErrNoRows is returned by Scan when QueryRow doesn't return a
|
||||
|
@ -368,7 +370,7 @@ func (db *DB) Begin() (*Tx, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// DriverDatabase returns the database's underlying driver.
|
||||
// Driver returns the database's underlying driver.
|
||||
func (db *DB) Driver() driver.Driver {
|
||||
return db.driver
|
||||
}
|
||||
|
@ -378,7 +380,7 @@ func (db *DB) Driver() driver.Driver {
|
|||
// A transaction must end with a call to Commit or Rollback.
|
||||
//
|
||||
// After a call to Commit or Rollback, all operations on the
|
||||
// transaction fail with ErrTransactionFinished.
|
||||
// transaction fail with ErrTxDone.
|
||||
type Tx struct {
|
||||
db *DB
|
||||
|
||||
|
@ -393,11 +395,11 @@ type Tx struct {
|
|||
|
||||
// done transitions from false to true exactly once, on Commit
|
||||
// or Rollback. once done, all operations fail with
|
||||
// ErrTransactionFinished.
|
||||
// ErrTxDone.
|
||||
done bool
|
||||
}
|
||||
|
||||
var ErrTransactionFinished = errors.New("sql: Transaction has already been committed or rolled back")
|
||||
var ErrTxDone = errors.New("sql: Transaction has already been committed or rolled back")
|
||||
|
||||
func (tx *Tx) close() {
|
||||
if tx.done {
|
||||
|
@ -411,7 +413,7 @@ func (tx *Tx) close() {
|
|||
|
||||
func (tx *Tx) grabConn() (driver.Conn, error) {
|
||||
if tx.done {
|
||||
return nil, ErrTransactionFinished
|
||||
return nil, ErrTxDone
|
||||
}
|
||||
tx.cimu.Lock()
|
||||
return tx.ci, nil
|
||||
|
@ -424,7 +426,7 @@ func (tx *Tx) releaseConn() {
|
|||
// Commit commits the transaction.
|
||||
func (tx *Tx) Commit() error {
|
||||
if tx.done {
|
||||
return ErrTransactionFinished
|
||||
return ErrTxDone
|
||||
}
|
||||
defer tx.close()
|
||||
return tx.txi.Commit()
|
||||
|
@ -433,7 +435,7 @@ func (tx *Tx) Commit() error {
|
|||
// Rollback aborts the transaction.
|
||||
func (tx *Tx) Rollback() error {
|
||||
if tx.done {
|
||||
return ErrTransactionFinished
|
||||
return ErrTxDone
|
||||
}
|
||||
defer tx.close()
|
||||
return tx.txi.Rollback()
|
||||
|
@ -523,10 +525,12 @@ func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
|
|||
|
||||
if execer, ok := ci.(driver.Execer); ok {
|
||||
resi, err := execer.Exec(query, args)
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
return result{resi}, nil
|
||||
}
|
||||
if err != driver.ErrSkip {
|
||||
return nil, err
|
||||
}
|
||||
return result{resi}, nil
|
||||
}
|
||||
|
||||
sti, err := ci.Prepare(query)
|
||||
|
@ -550,7 +554,7 @@ func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
|
|||
// Query executes a query that returns rows, typically a SELECT.
|
||||
func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
|
||||
if tx.done {
|
||||
return nil, ErrTransactionFinished
|
||||
return nil, ErrTxDone
|
||||
}
|
||||
stmt, err := tx.Prepare(query)
|
||||
if err != nil {
|
||||
|
@ -767,7 +771,7 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
|
|||
// Example usage:
|
||||
//
|
||||
// var name string
|
||||
// err := nameByUseridStmt.QueryRow(id).Scan(&s)
|
||||
// err := nameByUseridStmt.QueryRow(id).Scan(&name)
|
||||
func (s *Stmt) QueryRow(args ...interface{}) *Row {
|
||||
rows, err := s.Query(args...)
|
||||
if err != nil {
|
||||
|
|
|
@ -386,6 +386,38 @@ func TestNullByteSlice(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPointerParamsAndScans(t *testing.T) {
|
||||
db := newTestDB(t, "")
|
||||
defer closeDB(t, db)
|
||||
exec(t, db, "CREATE|t|id=int32,name=nullstring")
|
||||
|
||||
bob := "bob"
|
||||
var name *string
|
||||
|
||||
name = &bob
|
||||
exec(t, db, "INSERT|t|id=10,name=?", name)
|
||||
name = nil
|
||||
exec(t, db, "INSERT|t|id=20,name=?", name)
|
||||
|
||||
err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name)
|
||||
if err != nil {
|
||||
t.Fatalf("querying id 10: %v", err)
|
||||
}
|
||||
if name == nil {
|
||||
t.Errorf("id 10's name = nil; want bob")
|
||||
} else if *name != "bob" {
|
||||
t.Errorf("id 10's name = %q; want bob", *name)
|
||||
}
|
||||
|
||||
err = db.QueryRow("SELECT|t|name|id=?", 20).Scan(&name)
|
||||
if err != nil {
|
||||
t.Fatalf("querying id 20: %v", err)
|
||||
}
|
||||
if name != nil {
|
||||
t.Errorf("id 20 = %q; want nil", *name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryRowClosingStmt(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package macho implements access to Mach-O object files, as defined by
|
||||
// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html.
|
||||
// Package macho implements access to Mach-O object files.
|
||||
package macho
|
||||
|
||||
// High level access to low level data structures.
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
// Package binary implements translation between
|
||||
// unsigned integer values and byte sequences
|
||||
// and the reading and writing of fixed-size values.
|
||||
// A fixed-size value is either a fixed-size arithmetic
|
||||
// type (int8, uint8, int16, float32, complex64, ...)
|
||||
// or an array or struct containing only fixed-size values.
|
||||
package binary
|
||||
|
||||
import (
|
||||
|
@ -119,9 +122,6 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
|
|||
// Read reads structured binary data from r into data.
|
||||
// Data must be a pointer to a fixed-size value or a slice
|
||||
// of fixed-size values.
|
||||
// A fixed-size value is either a fixed-size arithmetic
|
||||
// type (int8, uint8, int16, float32, complex64, ...)
|
||||
// or an array or struct containing only fixed-size values.
|
||||
// Bytes read from r are decoded using the specified byte order
|
||||
// and written to successive fields of the data.
|
||||
func Read(r io.Reader, order ByteOrder, data interface{}) error {
|
||||
|
@ -176,11 +176,8 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
|
|||
}
|
||||
|
||||
// Write writes the binary representation of data into w.
|
||||
// Data must be a fixed-size value or a pointer to
|
||||
// a fixed-size value.
|
||||
// A fixed-size value is either a fixed-size arithmetic
|
||||
// type (int8, uint8, int16, float32, complex64, ...)
|
||||
// or an array or struct containing only fixed-size values.
|
||||
// Data must be a fixed-size value or a slice of fixed-size
|
||||
// values, or a pointer to such data.
|
||||
// Bytes written to w are encoded using the specified byte order
|
||||
// and read from successive fields of the data.
|
||||
func Write(w io.Writer, order ByteOrder, data interface{}) error {
|
||||
|
@ -253,6 +250,12 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Size returns how many bytes Write would generate to encode the value v, which
|
||||
// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
|
||||
func Size(v interface{}) int {
|
||||
return dataSize(reflect.Indirect(reflect.ValueOf(v)))
|
||||
}
|
||||
|
||||
// dataSize returns the number of bytes the actual data represented by v occupies in memory.
|
||||
// For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
|
||||
// it returns the length of the slice times the element size and does not count the memory
|
||||
|
@ -373,6 +376,7 @@ func (d *decoder) value(v reflect.Value) {
|
|||
for i := 0; i < l; i++ {
|
||||
d.value(v.Index(i))
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
l := v.NumField()
|
||||
for i := 0; i < l; i++ {
|
||||
|
@ -428,11 +432,13 @@ func (e *encoder) value(v reflect.Value) {
|
|||
for i := 0; i < l; i++ {
|
||||
e.value(v.Index(i))
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
l := v.NumField()
|
||||
for i := 0; i < l; i++ {
|
||||
e.value(v.Field(i))
|
||||
}
|
||||
|
||||
case reflect.Slice:
|
||||
l := v.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
|
|
|
@ -456,7 +456,7 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
|
|||
}
|
||||
if *(*unsafe.Pointer)(up) == nil {
|
||||
// Allocate object.
|
||||
*(*unsafe.Pointer)(up) = unsafe.New(rtyp)
|
||||
*(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer())
|
||||
}
|
||||
return *(*uintptr)(up)
|
||||
}
|
||||
|
@ -609,7 +609,7 @@ func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr,
|
|||
// 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)))
|
||||
v := reflect.NewAt(mtyp, unsafe.Pointer(p)).Elem()
|
||||
n := int(state.decodeUint())
|
||||
for i := 0; i < n; i++ {
|
||||
key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl)
|
||||
|
@ -662,7 +662,7 @@ func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintpt
|
|||
// 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.Data = reflect.MakeSlice(atyp, n, n).Pointer()
|
||||
hdrp.Cap = n
|
||||
}
|
||||
hdrp.Len = n
|
||||
|
@ -969,16 +969,16 @@ func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
|
|||
// 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)
|
||||
*(*unsafe.Pointer)(p) = unsafe.Pointer(reflect.New(ut.base).Pointer())
|
||||
}
|
||||
}
|
||||
// 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)))
|
||||
v = reflect.NewAt(rcvrType, unsafe.Pointer(&p)).Elem()
|
||||
} else {
|
||||
v = reflect.ValueOf(unsafe.Unreflect(rcvrType, p))
|
||||
v = reflect.NewAt(rcvrType, p).Elem()
|
||||
}
|
||||
state.dec.decodeGobDecoder(state, v)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// Need to compile package gob with debug.go to build this program.
|
||||
|
|
|
@ -590,7 +590,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
|
|||
// 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)))
|
||||
v := reflect.NewAt(t, unsafe.Pointer(p)).Elem()
|
||||
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.)
|
||||
|
@ -613,7 +613,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
|
|||
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)))
|
||||
v := reflect.NewAt(t, unsafe.Pointer(p)).Elem()
|
||||
iv := reflect.Indirect(v)
|
||||
if !state.sendZero && (!iv.IsValid() || iv.IsNil()) {
|
||||
return
|
||||
|
@ -645,9 +645,9 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
|
|||
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)))
|
||||
v = reflect.NewAt(rt, unsafe.Pointer(&p)).Elem()
|
||||
} else {
|
||||
v = reflect.ValueOf(unsafe.Unreflect(rt, p))
|
||||
v = reflect.NewAt(rt, p).Elem()
|
||||
}
|
||||
if !state.sendZero && isZero(v) {
|
||||
return
|
||||
|
|
|
@ -87,7 +87,7 @@ func TestInvalidErr(t *testing.T) {
|
|||
dst := make([]byte, DecodedLen(len(test.in)))
|
||||
_, err := Decode(dst, []byte(test.in))
|
||||
if err == nil {
|
||||
t.Errorf("#%d: expected error; got none")
|
||||
t.Errorf("#%d: expected error; got none", i)
|
||||
} else if err.Error() != test.err {
|
||||
t.Errorf("#%d: got: %v want: %v", i, err, test.err)
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ func TestInvalidStringErr(t *testing.T) {
|
|||
for i, test := range errTests {
|
||||
_, err := DecodeString(test.in)
|
||||
if err == nil {
|
||||
t.Errorf("#%d: expected error; got none")
|
||||
t.Errorf("#%d: expected error; got none", i)
|
||||
} else if err.Error() != test.err {
|
||||
t.Errorf("#%d: got: %v want: %v", i, err, test.err)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@ type Decoder struct {
|
|||
}
|
||||
|
||||
// NewDecoder returns a new decoder that reads from r.
|
||||
//
|
||||
// The decoder introduces its own buffering and may
|
||||
// read data from r beyond the JSON values requested.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
return &Decoder{r: r}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
package xml
|
||||
|
||||
import "time"
|
||||
|
||||
var atomValue = &Feed{
|
||||
XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
|
||||
Title: "Example Feed",
|
||||
|
@ -24,11 +26,10 @@ var atomValue = &Feed{
|
|||
}
|
||||
|
||||
var atomXml = `` +
|
||||
`<feed xmlns="http://www.w3.org/2005/Atom">` +
|
||||
`<feed xmlns="http://www.w3.org/2005/Atom" updated="2003-12-13T18:30:02Z">` +
|
||||
`<title>Example Feed</title>` +
|
||||
`<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>` +
|
||||
`<link href="http://example.org/"></link>` +
|
||||
`<updated>2003-12-13T18:30:02Z</updated>` +
|
||||
`<author><name>John Doe</name><uri></uri><email></email></author>` +
|
||||
`<entry>` +
|
||||
`<title>Atom-Powered Robots Run Amok</title>` +
|
||||
|
@ -40,8 +41,12 @@ var atomXml = `` +
|
|||
`</entry>` +
|
||||
`</feed>`
|
||||
|
||||
func ParseTime(str string) Time {
|
||||
return Time(str)
|
||||
func ParseTime(str string) time.Time {
|
||||
t, err := time.Parse(time.RFC3339, str)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func NewText(text string) Text {
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -52,6 +53,10 @@ const (
|
|||
// - a field with tag ",comment" is written as an XML comment, not
|
||||
// subject to the usual marshalling procedure. It must not contain
|
||||
// the "--" string within it.
|
||||
// - a field with a tag including the "omitempty" option is omitted
|
||||
// if the field value is empty. The empty values are false, 0, any
|
||||
// nil pointer or interface value, and any array, slice, map, or
|
||||
// string of length zero.
|
||||
//
|
||||
// If a field uses a tag "a>b>c", then the element c will be nested inside
|
||||
// parent elements a and b. Fields that appear next to each other that name
|
||||
|
@ -63,6 +68,8 @@ const (
|
|||
// FirstName string `xml:"person>name>first"`
|
||||
// LastName string `xml:"person>name>last"`
|
||||
// Age int `xml:"person>age"`
|
||||
// Height float `xml:"person>height,omitempty"`
|
||||
// Married bool `xml:"person>married"`
|
||||
// }
|
||||
//
|
||||
// xml.Marshal(&Result{Id: 13, FirstName: "John", LastName: "Doe", Age: 42})
|
||||
|
@ -76,6 +83,7 @@ const (
|
|||
// <last>Doe</last>
|
||||
// </name>
|
||||
// <age>42</age>
|
||||
// <married>false</married>
|
||||
// </person>
|
||||
// </result>
|
||||
//
|
||||
|
@ -116,6 +124,9 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
|
|||
if !val.IsValid() {
|
||||
return nil
|
||||
}
|
||||
if finfo != nil && finfo.flags&fOmitEmpty != 0 && isEmptyValue(val) {
|
||||
return nil
|
||||
}
|
||||
|
||||
kind := val.Kind()
|
||||
typ := val.Type()
|
||||
|
@ -183,12 +194,8 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
|
|||
continue
|
||||
}
|
||||
fv := val.FieldByIndex(finfo.idx)
|
||||
switch fv.Kind() {
|
||||
case reflect.String, reflect.Array, reflect.Slice:
|
||||
// TODO: Should we really do this once ,omitempty is in?
|
||||
if fv.Len() == 0 {
|
||||
continue
|
||||
}
|
||||
if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
|
||||
continue
|
||||
}
|
||||
p.WriteByte(' ')
|
||||
p.WriteString(finfo.name)
|
||||
|
@ -217,7 +224,14 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
var timeType = reflect.TypeOf(time.Time{})
|
||||
|
||||
func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error {
|
||||
// Normally we don't see structs, but this can happen for an attribute.
|
||||
if val.Type() == timeType {
|
||||
p.WriteString(val.Interface().(time.Time).Format(time.RFC3339Nano))
|
||||
return nil
|
||||
}
|
||||
switch val.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
p.WriteString(strconv.FormatInt(val.Int(), 10))
|
||||
|
@ -249,6 +263,10 @@ func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error {
|
|||
var ddBytes = []byte("--")
|
||||
|
||||
func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
|
||||
if val.Type() == timeType {
|
||||
p.WriteString(val.Interface().(time.Time).Format(time.RFC3339Nano))
|
||||
return nil
|
||||
}
|
||||
s := parentStack{printer: p}
|
||||
for i := range tinfo.fields {
|
||||
finfo := &tinfo.fields[i]
|
||||
|
@ -378,3 +396,21 @@ type UnsupportedTypeError struct {
|
|||
func (e *UnsupportedTypeError) Error() string {
|
||||
return "xml: unsupported type: " + e.Type.String()
|
||||
}
|
||||
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DriveType int
|
||||
|
@ -38,14 +39,14 @@ type NamedType string
|
|||
|
||||
type Port struct {
|
||||
XMLName struct{} `xml:"port"`
|
||||
Type string `xml:"type,attr"`
|
||||
Type string `xml:"type,attr,omitempty"`
|
||||
Comment string `xml:",comment"`
|
||||
Number string `xml:",chardata"`
|
||||
}
|
||||
|
||||
type Domain struct {
|
||||
XMLName struct{} `xml:"domain"`
|
||||
Country string `xml:",attr"`
|
||||
Country string `xml:",attr,omitempty"`
|
||||
Name []byte `xml:",chardata"`
|
||||
Comment []byte `xml:",comment"`
|
||||
}
|
||||
|
@ -149,11 +150,33 @@ type NameInField struct {
|
|||
|
||||
type AttrTest struct {
|
||||
Int int `xml:",attr"`
|
||||
Lower int `xml:"int,attr"`
|
||||
Named int `xml:"int,attr"`
|
||||
Float float64 `xml:",attr"`
|
||||
Uint8 uint8 `xml:",attr"`
|
||||
Bool bool `xml:",attr"`
|
||||
Str string `xml:",attr"`
|
||||
Bytes []byte `xml:",attr"`
|
||||
}
|
||||
|
||||
type OmitAttrTest struct {
|
||||
Int int `xml:",attr,omitempty"`
|
||||
Named int `xml:"int,attr,omitempty"`
|
||||
Float float64 `xml:",attr,omitempty"`
|
||||
Uint8 uint8 `xml:",attr,omitempty"`
|
||||
Bool bool `xml:",attr,omitempty"`
|
||||
Str string `xml:",attr,omitempty"`
|
||||
Bytes []byte `xml:",attr,omitempty"`
|
||||
}
|
||||
|
||||
type OmitFieldTest struct {
|
||||
Int int `xml:",omitempty"`
|
||||
Named int `xml:"int,omitempty"`
|
||||
Float float64 `xml:",omitempty"`
|
||||
Uint8 uint8 `xml:",omitempty"`
|
||||
Bool bool `xml:",omitempty"`
|
||||
Str string `xml:",omitempty"`
|
||||
Bytes []byte `xml:",omitempty"`
|
||||
Ptr *PresenceTest `xml:",omitempty"`
|
||||
}
|
||||
|
||||
type AnyTest struct {
|
||||
|
@ -234,6 +257,12 @@ var marshalTests = []struct {
|
|||
{Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
|
||||
{Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
|
||||
|
||||
// Test time.
|
||||
{
|
||||
Value: &Plain{time.Unix(1e9, 123456789).UTC()},
|
||||
ExpectXML: `<Plain><V>2001-09-09T01:46:40.123456789Z</V></Plain>`,
|
||||
},
|
||||
|
||||
// A pointer to struct{} may be used to test for an element's presence.
|
||||
{
|
||||
Value: &PresenceTest{new(struct{})},
|
||||
|
@ -549,13 +578,65 @@ var marshalTests = []struct {
|
|||
{
|
||||
Value: &AttrTest{
|
||||
Int: 8,
|
||||
Lower: 9,
|
||||
Named: 9,
|
||||
Float: 23.5,
|
||||
Uint8: 255,
|
||||
Bool: true,
|
||||
Str: "s",
|
||||
Str: "str",
|
||||
Bytes: []byte("byt"),
|
||||
},
|
||||
ExpectXML: `<AttrTest Int="8" int="9" Float="23.5" Uint8="255" Bool="true" Str="s"></AttrTest>`,
|
||||
ExpectXML: `<AttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
|
||||
` Bool="true" Str="str" Bytes="byt"></AttrTest>`,
|
||||
},
|
||||
{
|
||||
Value: &AttrTest{Bytes: []byte{}},
|
||||
ExpectXML: `<AttrTest Int="0" int="0" Float="0" Uint8="0"` +
|
||||
` Bool="false" Str="" Bytes=""></AttrTest>`,
|
||||
},
|
||||
{
|
||||
Value: &OmitAttrTest{
|
||||
Int: 8,
|
||||
Named: 9,
|
||||
Float: 23.5,
|
||||
Uint8: 255,
|
||||
Bool: true,
|
||||
Str: "str",
|
||||
Bytes: []byte("byt"),
|
||||
},
|
||||
ExpectXML: `<OmitAttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
|
||||
` Bool="true" Str="str" Bytes="byt"></OmitAttrTest>`,
|
||||
},
|
||||
{
|
||||
Value: &OmitAttrTest{},
|
||||
ExpectXML: `<OmitAttrTest></OmitAttrTest>`,
|
||||
},
|
||||
|
||||
// omitempty on fields
|
||||
{
|
||||
Value: &OmitFieldTest{
|
||||
Int: 8,
|
||||
Named: 9,
|
||||
Float: 23.5,
|
||||
Uint8: 255,
|
||||
Bool: true,
|
||||
Str: "str",
|
||||
Bytes: []byte("byt"),
|
||||
Ptr: &PresenceTest{},
|
||||
},
|
||||
ExpectXML: `<OmitFieldTest>` +
|
||||
`<Int>8</Int>` +
|
||||
`<int>9</int>` +
|
||||
`<Float>23.5</Float>` +
|
||||
`<Uint8>255</Uint8>` +
|
||||
`<Bool>true</Bool>` +
|
||||
`<Str>str</Str>` +
|
||||
`<Bytes>byt</Bytes>` +
|
||||
`<Ptr></Ptr>` +
|
||||
`</OmitFieldTest>`,
|
||||
},
|
||||
{
|
||||
Value: &OmitFieldTest{},
|
||||
ExpectXML: `<OmitFieldTest></OmitFieldTest>`,
|
||||
},
|
||||
|
||||
// Test ",any"
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BUG(rsc): Mapping between XML elements and data structures is inherently flawed:
|
||||
|
@ -270,6 +271,10 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
|
|||
v.Set(reflect.ValueOf(start.Name))
|
||||
break
|
||||
}
|
||||
if typ == timeType {
|
||||
saveData = v
|
||||
break
|
||||
}
|
||||
|
||||
sv = v
|
||||
tinfo, err = getTypeInfo(typ)
|
||||
|
@ -473,6 +478,14 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
|
|||
src = []byte{}
|
||||
}
|
||||
t.SetBytes(src)
|
||||
case reflect.Struct:
|
||||
if t.Type() == timeType {
|
||||
tv, err := time.Parse(time.RFC3339, string(src))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.Set(reflect.ValueOf(tv))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package xml
|
|||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Stripped down Atom feed data structures.
|
||||
|
@ -24,7 +25,7 @@ func TestUnmarshalFeed(t *testing.T) {
|
|||
// hget http://codereview.appspot.com/rss/mine/rsc
|
||||
const atomFeedString = `
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us"><title>Code Review - My issues</title><link href="http://codereview.appspot.com/" rel="alternate"></link><link href="http://codereview.appspot.com/rss/mine/rsc" rel="self"></link><id>http://codereview.appspot.com/</id><updated>2009-10-04T01:35:58+00:00</updated><author><name>rietveld<></name></author><entry><title>rietveld: an attempt at pubsubhubbub
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us" updated="2009-10-04T01:35:58+00:00"><title>Code Review - My issues</title><link href="http://codereview.appspot.com/" rel="alternate"></link><link href="http://codereview.appspot.com/rss/mine/rsc" rel="self"></link><id>http://codereview.appspot.com/</id><author><name>rietveld<></name></author><entry><title>rietveld: an attempt at pubsubhubbub
|
||||
</title><link href="http://codereview.appspot.com/126085" rel="alternate"></link><updated>2009-10-04T01:35:58+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:134d9179c41f806be79b3a5f7877d19a</id><summary type="html">
|
||||
An attempt at adding pubsubhubbub support to Rietveld.
|
||||
http://code.google.com/p/pubsubhubbub
|
||||
|
@ -78,26 +79,26 @@ not being used from outside intra_region_diff.py.
|
|||
</summary></entry></feed> `
|
||||
|
||||
type Feed struct {
|
||||
XMLName Name `xml:"http://www.w3.org/2005/Atom feed"`
|
||||
Title string `xml:"title"`
|
||||
Id string `xml:"id"`
|
||||
Link []Link `xml:"link"`
|
||||
Updated Time `xml:"updated"`
|
||||
Author Person `xml:"author"`
|
||||
Entry []Entry `xml:"entry"`
|
||||
XMLName Name `xml:"http://www.w3.org/2005/Atom feed"`
|
||||
Title string `xml:"title"`
|
||||
Id string `xml:"id"`
|
||||
Link []Link `xml:"link"`
|
||||
Updated time.Time `xml:"updated,attr"`
|
||||
Author Person `xml:"author"`
|
||||
Entry []Entry `xml:"entry"`
|
||||
}
|
||||
|
||||
type Entry struct {
|
||||
Title string `xml:"title"`
|
||||
Id string `xml:"id"`
|
||||
Link []Link `xml:"link"`
|
||||
Updated Time `xml:"updated"`
|
||||
Author Person `xml:"author"`
|
||||
Summary Text `xml:"summary"`
|
||||
Title string `xml:"title"`
|
||||
Id string `xml:"id"`
|
||||
Link []Link `xml:"link"`
|
||||
Updated time.Time `xml:"updated"`
|
||||
Author Person `xml:"author"`
|
||||
Summary Text `xml:"summary"`
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
Rel string `xml:"rel,attr"`
|
||||
Rel string `xml:"rel,attr,omitempty"`
|
||||
Href string `xml:"href,attr"`
|
||||
}
|
||||
|
||||
|
@ -109,12 +110,10 @@ type Person struct {
|
|||
}
|
||||
|
||||
type Text struct {
|
||||
Type string `xml:"type,attr"`
|
||||
Type string `xml:"type,attr,omitempty"`
|
||||
Body string `xml:",chardata"`
|
||||
}
|
||||
|
||||
type Time string
|
||||
|
||||
var atomFeed = Feed{
|
||||
XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
|
||||
Title: "Code Review - My issues",
|
||||
|
@ -123,7 +122,7 @@ var atomFeed = Feed{
|
|||
{Rel: "self", Href: "http://codereview.appspot.com/rss/mine/rsc"},
|
||||
},
|
||||
Id: "http://codereview.appspot.com/",
|
||||
Updated: "2009-10-04T01:35:58+00:00",
|
||||
Updated: ParseTime("2009-10-04T01:35:58+00:00"),
|
||||
Author: Person{
|
||||
Name: "rietveld<>",
|
||||
InnerXML: "<name>rietveld<></name>",
|
||||
|
@ -134,7 +133,7 @@ var atomFeed = Feed{
|
|||
Link: []Link{
|
||||
{Rel: "alternate", Href: "http://codereview.appspot.com/126085"},
|
||||
},
|
||||
Updated: "2009-10-04T01:35:58+00:00",
|
||||
Updated: ParseTime("2009-10-04T01:35:58+00:00"),
|
||||
Author: Person{
|
||||
Name: "email-address-removed",
|
||||
InnerXML: "<name>email-address-removed</name>",
|
||||
|
@ -181,7 +180,7 @@ the top of feeds.py marked NOTE(rsc).
|
|||
Link: []Link{
|
||||
{Rel: "alternate", Href: "http://codereview.appspot.com/124106"},
|
||||
},
|
||||
Updated: "2009-10-03T23:02:17+00:00",
|
||||
Updated: ParseTime("2009-10-03T23:02:17+00:00"),
|
||||
Author: Person{
|
||||
Name: "email-address-removed",
|
||||
InnerXML: "<name>email-address-removed</name>",
|
||||
|
|
|
@ -36,8 +36,7 @@ const (
|
|||
fComment
|
||||
fAny
|
||||
|
||||
// TODO:
|
||||
//fOmitEmpty
|
||||
fOmitEmpty
|
||||
|
||||
fMode = fElement | fAttr | fCharData | fInnerXml | fComment | fAny
|
||||
)
|
||||
|
@ -133,20 +132,28 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
|
|||
finfo.flags |= fComment
|
||||
case "any":
|
||||
finfo.flags |= fAny
|
||||
case "omitempty":
|
||||
finfo.flags |= fOmitEmpty
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the flags used.
|
||||
valid := true
|
||||
switch mode := finfo.flags & fMode; mode {
|
||||
case 0:
|
||||
finfo.flags |= fElement
|
||||
case fAttr, fCharData, fInnerXml, fComment, fAny:
|
||||
if f.Name != "XMLName" && (tag == "" || mode == fAttr) {
|
||||
break
|
||||
if f.Name == "XMLName" || tag != "" && mode != fAttr {
|
||||
valid = false
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
// This will also catch multiple modes in a single field.
|
||||
valid = false
|
||||
}
|
||||
if finfo.flags&fOmitEmpty != 0 && finfo.flags&(fElement|fAttr) == 0 {
|
||||
valid = false
|
||||
}
|
||||
if !valid {
|
||||
return nil, fmt.Errorf("xml: invalid tag in field %s of type %s: %q",
|
||||
f.Name, typ, f.Tag.Get("xml"))
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ func (rb *reorderBuffer) insert(src input, i int, info runeInfo) bool {
|
|||
}
|
||||
}
|
||||
if info.hasDecomposition() {
|
||||
dcomp := rb.f.decompose(src, i)
|
||||
dcomp := info.decomposition()
|
||||
rb.tmpBytes = inputBytes(dcomp)
|
||||
for i := 0; i < len(dcomp); {
|
||||
info = rb.f.info(&rb.tmpBytes, i)
|
||||
|
|
|
@ -6,25 +6,50 @@ package norm
|
|||
|
||||
// This file contains Form-specific logic and wrappers for data in tables.go.
|
||||
|
||||
// Rune info is stored in a separate trie per composing form. A composing form
|
||||
// and its corresponding decomposing form share the same trie. Each trie maps
|
||||
// a rune to a uint16. The values take two forms. For v >= 0x8000:
|
||||
// bits
|
||||
// 0..8: ccc
|
||||
// 9..12: qcInfo (see below). isYesD is always true (no decompostion).
|
||||
// 16: 1
|
||||
// For v < 0x8000, the respective rune has a decomposition and v is an index
|
||||
// into a byte array of UTF-8 decomposition sequences and additional info and
|
||||
// has the form:
|
||||
// <header> <decomp_byte>* [<tccc> [<lccc>]]
|
||||
// The header contains the number of bytes in the decomposition (excluding this
|
||||
// length byte). The two most significant bits of this lenght byte correspond
|
||||
// to bit 2 and 3 of qcIfo (see below). The byte sequence itself starts at v+1.
|
||||
// The byte sequence is followed by a trailing and leading CCC if the values
|
||||
// for these are not zero. The value of v determines which ccc are appended
|
||||
// to the sequences. For v < firstCCC, there are none, for v >= firstCCC,
|
||||
// the seqence is followed by a trailing ccc, and for v >= firstLeadingCC
|
||||
// there is an additional leading ccc.
|
||||
|
||||
const (
|
||||
qcInfoMask = 0xF // to clear all but the relevant bits in a qcInfo
|
||||
headerLenMask = 0x3F // extract the lenght value from the header byte
|
||||
headerFlagsMask = 0xC0 // extract the qcInfo bits from the header byte
|
||||
)
|
||||
|
||||
// runeInfo is a representation for the data stored in charinfoTrie.
|
||||
type runeInfo struct {
|
||||
pos uint8 // start position in reorderBuffer; used in composition.go
|
||||
size uint8 // length of UTF-8 encoding of this rune
|
||||
ccc uint8 // canonical combining class
|
||||
ccc uint8 // leading canonical combining class (ccc if not decomposition)
|
||||
tccc uint8 // trailing canonical combining class (ccc if not decomposition)
|
||||
flags qcInfo // quick check flags
|
||||
index uint16
|
||||
}
|
||||
|
||||
// functions dispatchable per form
|
||||
type lookupFunc func(b input, i int) runeInfo
|
||||
type decompFunc func(b input, i int) []byte
|
||||
|
||||
// formInfo holds Form-specific functions and tables.
|
||||
type formInfo struct {
|
||||
form Form
|
||||
|
||||
form Form
|
||||
composing, compatibility bool // form type
|
||||
|
||||
decompose decompFunc
|
||||
info lookupFunc
|
||||
info lookupFunc
|
||||
}
|
||||
|
||||
var formTable []*formInfo
|
||||
|
@ -38,10 +63,8 @@ func init() {
|
|||
f.form = Form(i)
|
||||
if Form(i) == NFKD || Form(i) == NFKC {
|
||||
f.compatibility = true
|
||||
f.decompose = decomposeNFKC
|
||||
f.info = lookupInfoNFKC
|
||||
} else {
|
||||
f.decompose = decomposeNFC
|
||||
f.info = lookupInfoNFC
|
||||
}
|
||||
if Form(i) == NFC || Form(i) == NFKC {
|
||||
|
@ -76,8 +99,6 @@ func (i runeInfo) boundaryAfter() bool {
|
|||
//
|
||||
// When all 4 bits are zero, the character is inert, meaning it is never
|
||||
// influenced by normalization.
|
||||
//
|
||||
// We pack the bits for both NFC/D and NFKC/D in one byte.
|
||||
type qcInfo uint8
|
||||
|
||||
func (i runeInfo) isYesC() bool { return i.flags&0x4 == 0 }
|
||||
|
@ -91,22 +112,12 @@ func (r runeInfo) isInert() bool {
|
|||
return r.flags&0xf == 0 && r.ccc == 0
|
||||
}
|
||||
|
||||
// Wrappers for tables.go
|
||||
|
||||
// The 16-bit value of the decomposition tries is an index into a byte
|
||||
// array of UTF-8 decomposition sequences. The first byte is the number
|
||||
// of bytes in the decomposition (excluding this length byte). The actual
|
||||
// sequence starts at the offset+1.
|
||||
func decomposeNFC(s input, i int) []byte {
|
||||
p := s.decomposeNFC(i)
|
||||
n := decomps[p]
|
||||
p++
|
||||
return decomps[p : p+uint16(n)]
|
||||
}
|
||||
|
||||
func decomposeNFKC(s input, i int) []byte {
|
||||
p := s.decomposeNFKC(i)
|
||||
n := decomps[p]
|
||||
func (r runeInfo) decomposition() []byte {
|
||||
if r.index == 0 {
|
||||
return nil
|
||||
}
|
||||
p := r.index
|
||||
n := decomps[p] & 0x3F
|
||||
p++
|
||||
return decomps[p : p+uint16(n)]
|
||||
}
|
||||
|
@ -124,16 +135,40 @@ func combine(a, b rune) rune {
|
|||
return recompMap[key]
|
||||
}
|
||||
|
||||
// The 16-bit character info has the following bit layout:
|
||||
// 0..7 CCC value.
|
||||
// 8..11 qcInfo for NFC/NFD
|
||||
// 12..15 qcInfo for NFKC/NFKD
|
||||
func lookupInfoNFC(b input, i int) runeInfo {
|
||||
v, sz := b.charinfo(i)
|
||||
return runeInfo{size: uint8(sz), ccc: uint8(v), flags: qcInfo(v >> 8)}
|
||||
v, sz := b.charinfoNFC(i)
|
||||
return compInfo(v, sz)
|
||||
}
|
||||
|
||||
func lookupInfoNFKC(b input, i int) runeInfo {
|
||||
v, sz := b.charinfo(i)
|
||||
return runeInfo{size: uint8(sz), ccc: uint8(v), flags: qcInfo(v >> 12)}
|
||||
v, sz := b.charinfoNFKC(i)
|
||||
return compInfo(v, sz)
|
||||
}
|
||||
|
||||
// compInfo converts the information contained in v and sz
|
||||
// to a runeInfo. See the comment at the top of the file
|
||||
// for more information on the format.
|
||||
func compInfo(v uint16, sz int) runeInfo {
|
||||
if v == 0 {
|
||||
return runeInfo{size: uint8(sz)}
|
||||
} else if v >= 0x8000 {
|
||||
return runeInfo{
|
||||
size: uint8(sz),
|
||||
ccc: uint8(v),
|
||||
tccc: uint8(v),
|
||||
flags: qcInfo(v>>8) & qcInfoMask,
|
||||
}
|
||||
}
|
||||
// has decomposition
|
||||
h := decomps[v]
|
||||
f := (qcInfo(h&headerFlagsMask) >> 4) | 0x1
|
||||
ri := runeInfo{size: uint8(sz), flags: f, index: v}
|
||||
if v >= firstCCC {
|
||||
v += uint16(h&headerLenMask) + 1
|
||||
ri.tccc = decomps[v]
|
||||
if v >= firstLeadingCCC {
|
||||
ri.ccc = decomps[v+1]
|
||||
}
|
||||
}
|
||||
return ri
|
||||
}
|
||||
|
|
|
@ -11,9 +11,8 @@ type input interface {
|
|||
skipNonStarter(p int) int
|
||||
appendSlice(buf []byte, s, e int) []byte
|
||||
copySlice(buf []byte, s, e int)
|
||||
charinfo(p int) (uint16, int)
|
||||
decomposeNFC(p int) uint16
|
||||
decomposeNFKC(p int) uint16
|
||||
charinfoNFC(p int) (uint16, int)
|
||||
charinfoNFKC(p int) (uint16, int)
|
||||
hangul(p int) rune
|
||||
}
|
||||
|
||||
|
@ -42,16 +41,12 @@ func (s inputString) copySlice(buf []byte, b, e int) {
|
|||
copy(buf, s[b:e])
|
||||
}
|
||||
|
||||
func (s inputString) charinfo(p int) (uint16, int) {
|
||||
return charInfoTrie.lookupString(string(s[p:]))
|
||||
func (s inputString) charinfoNFC(p int) (uint16, int) {
|
||||
return nfcTrie.lookupString(string(s[p:]))
|
||||
}
|
||||
|
||||
func (s inputString) decomposeNFC(p int) uint16 {
|
||||
return nfcDecompTrie.lookupStringUnsafe(string(s[p:]))
|
||||
}
|
||||
|
||||
func (s inputString) decomposeNFKC(p int) uint16 {
|
||||
return nfkcDecompTrie.lookupStringUnsafe(string(s[p:]))
|
||||
func (s inputString) charinfoNFKC(p int) (uint16, int) {
|
||||
return nfkcTrie.lookupString(string(s[p:]))
|
||||
}
|
||||
|
||||
func (s inputString) hangul(p int) rune {
|
||||
|
@ -84,16 +79,12 @@ func (s inputBytes) copySlice(buf []byte, b, e int) {
|
|||
copy(buf, s[b:e])
|
||||
}
|
||||
|
||||
func (s inputBytes) charinfo(p int) (uint16, int) {
|
||||
return charInfoTrie.lookup(s[p:])
|
||||
func (s inputBytes) charinfoNFC(p int) (uint16, int) {
|
||||
return nfcTrie.lookup(s[p:])
|
||||
}
|
||||
|
||||
func (s inputBytes) decomposeNFC(p int) uint16 {
|
||||
return nfcDecompTrie.lookupUnsafe(s[p:])
|
||||
}
|
||||
|
||||
func (s inputBytes) decomposeNFKC(p int) uint16 {
|
||||
return nfkcDecompTrie.lookupUnsafe(s[p:])
|
||||
func (s inputBytes) charinfoNFKC(p int) (uint16, int) {
|
||||
return nfkcTrie.lookup(s[p:])
|
||||
}
|
||||
|
||||
func (s inputBytes) hangul(p int) rune {
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Normalization table generator.
|
||||
// Data read from the web.
|
||||
// See forminfo.go for a description of the trie values associated with each rune.
|
||||
|
||||
package main
|
||||
|
||||
|
@ -17,6 +20,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
@ -187,18 +191,14 @@ func (f FormInfo) String() string {
|
|||
fmt.Fprintf(buf, " cmbBackward: %v\n", f.combinesBackward)
|
||||
fmt.Fprintf(buf, " isOneWay: %v\n", f.isOneWay)
|
||||
fmt.Fprintf(buf, " inDecomp: %v\n", f.inDecomp)
|
||||
fmt.Fprintf(buf, " decomposition: %v\n", f.decomp)
|
||||
fmt.Fprintf(buf, " expandedDecomp: %v\n", f.expandedDecomp)
|
||||
fmt.Fprintf(buf, " decomposition: %X\n", f.decomp)
|
||||
fmt.Fprintf(buf, " expandedDecomp: %X\n", f.expandedDecomp)
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
type Decomposition []rune
|
||||
|
||||
func (d Decomposition) String() string {
|
||||
return fmt.Sprintf("%.4X", d)
|
||||
}
|
||||
|
||||
func openReader(file string) (input io.ReadCloser) {
|
||||
if *localFiles {
|
||||
f, err := os.Open(file)
|
||||
|
@ -571,80 +571,121 @@ func makeEntry(f *FormInfo) uint16 {
|
|||
return e
|
||||
}
|
||||
|
||||
// Bits
|
||||
// 0..8: CCC
|
||||
// 9..12: NF(C|D) qc bits.
|
||||
// 13..16: NFK(C|D) qc bits.
|
||||
func makeCharInfo(c Char) uint16 {
|
||||
e := makeEntry(&c.forms[FCompatibility])
|
||||
e = e<<4 | makeEntry(&c.forms[FCanonical])
|
||||
e = e<<8 | uint16(c.ccc)
|
||||
return e
|
||||
// decompSet keeps track of unique decompositions, grouped by whether
|
||||
// the decomposition is followed by a trailing and/or leading CCC.
|
||||
type decompSet [4]map[string]bool
|
||||
|
||||
func makeDecompSet() decompSet {
|
||||
m := decompSet{}
|
||||
for i, _ := range m {
|
||||
m[i] = make(map[string]bool)
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *decompSet) insert(key int, s string) {
|
||||
m[key][s] = true
|
||||
}
|
||||
|
||||
func printCharInfoTables() int {
|
||||
// Quick Check + CCC trie.
|
||||
t := newNode()
|
||||
for i, char := range chars {
|
||||
v := makeCharInfo(char)
|
||||
if v != 0 {
|
||||
t.insert(rune(i), v)
|
||||
mkstr := func(r rune, f *FormInfo) (int, string) {
|
||||
d := f.expandedDecomp
|
||||
s := string([]rune(d))
|
||||
if max := 1 << 6; len(s) >= max {
|
||||
const msg = "%U: too many bytes in decomposition: %d >= %d"
|
||||
logger.Fatalf(msg, r, len(s), max)
|
||||
}
|
||||
head := uint8(len(s))
|
||||
if f.quickCheck[MComposed] != QCYes {
|
||||
head |= 0x40
|
||||
}
|
||||
if f.combinesForward {
|
||||
head |= 0x80
|
||||
}
|
||||
s = string([]byte{head}) + s
|
||||
|
||||
lccc := ccc(d[0])
|
||||
tccc := ccc(d[len(d)-1])
|
||||
if tccc < lccc && lccc != 0 {
|
||||
const msg = "%U: lccc (%d) must be <= tcc (%d)"
|
||||
logger.Fatalf(msg, r, lccc, tccc)
|
||||
}
|
||||
index := 0
|
||||
if tccc > 0 || lccc > 0 {
|
||||
s += string([]byte{tccc})
|
||||
index = 1
|
||||
if lccc > 0 {
|
||||
s += string([]byte{lccc})
|
||||
index |= 2
|
||||
}
|
||||
}
|
||||
return index, s
|
||||
}
|
||||
return t.printTables("charInfo")
|
||||
}
|
||||
|
||||
func printDecompositionTables() int {
|
||||
decompositions := bytes.NewBuffer(make([]byte, 0, 10000))
|
||||
size := 0
|
||||
|
||||
// Map decompositions
|
||||
positionMap := make(map[string]uint16)
|
||||
decompSet := makeDecompSet()
|
||||
|
||||
// Store the uniqued decompositions in a byte buffer,
|
||||
// preceded by their byte length.
|
||||
for _, c := range chars {
|
||||
for f := 0; f < 2; f++ {
|
||||
d := c.forms[f].expandedDecomp
|
||||
s := string([]rune(d))
|
||||
if _, ok := positionMap[s]; !ok {
|
||||
p := decompositions.Len()
|
||||
decompositions.WriteByte(uint8(len(s)))
|
||||
decompositions.WriteString(s)
|
||||
positionMap[s] = uint16(p)
|
||||
for _, f := range c.forms {
|
||||
if len(f.expandedDecomp) == 0 {
|
||||
continue
|
||||
}
|
||||
if f.combinesBackward {
|
||||
logger.Fatalf("%U: combinesBackward and decompose", c.codePoint)
|
||||
}
|
||||
index, s := mkstr(c.codePoint, &f)
|
||||
decompSet.insert(index, s)
|
||||
}
|
||||
}
|
||||
|
||||
decompositions := bytes.NewBuffer(make([]byte, 0, 10000))
|
||||
size := 0
|
||||
positionMap := make(map[string]uint16)
|
||||
decompositions.WriteString("\000")
|
||||
cname := []string{"firstCCC", "firstLeadingCCC", "", "lastDecomp"}
|
||||
fmt.Println("const (")
|
||||
for i, m := range decompSet {
|
||||
sa := []string{}
|
||||
for s, _ := range m {
|
||||
sa = append(sa, s)
|
||||
}
|
||||
sort.Strings(sa)
|
||||
for _, s := range sa {
|
||||
p := decompositions.Len()
|
||||
decompositions.WriteString(s)
|
||||
positionMap[s] = uint16(p)
|
||||
}
|
||||
if cname[i] != "" {
|
||||
fmt.Printf("%s = 0x%X\n", cname[i], decompositions.Len())
|
||||
}
|
||||
}
|
||||
fmt.Println("maxDecomp = 0x8000")
|
||||
fmt.Println(")")
|
||||
b := decompositions.Bytes()
|
||||
printBytes(b, "decomps")
|
||||
size += len(b)
|
||||
|
||||
nfcT := newNode()
|
||||
nfkcT := newNode()
|
||||
for i, c := range chars {
|
||||
d := c.forms[FCanonical].expandedDecomp
|
||||
if len(d) != 0 {
|
||||
nfcT.insert(rune(i), positionMap[string([]rune(d))])
|
||||
if ccc(c.codePoint) != ccc(d[0]) {
|
||||
// We assume the lead ccc of a decomposition is !=0 in this case.
|
||||
if ccc(d[0]) == 0 {
|
||||
logger.Fatal("Expected differing CCC to be non-zero.")
|
||||
}
|
||||
}
|
||||
}
|
||||
d = c.forms[FCompatibility].expandedDecomp
|
||||
if len(d) != 0 {
|
||||
nfkcT.insert(rune(i), positionMap[string([]rune(d))])
|
||||
if ccc(c.codePoint) != ccc(d[0]) {
|
||||
// We assume the lead ccc of a decomposition is !=0 in this case.
|
||||
if ccc(d[0]) == 0 {
|
||||
logger.Fatal("Expected differing CCC to be non-zero.")
|
||||
varnames := []string{"nfc", "nfkc"}
|
||||
for i := 0; i < FNumberOfFormTypes; i++ {
|
||||
trie := newNode()
|
||||
for r, c := range chars {
|
||||
f := c.forms[i]
|
||||
d := f.expandedDecomp
|
||||
if len(d) != 0 {
|
||||
_, key := mkstr(c.codePoint, &f)
|
||||
trie.insert(rune(r), positionMap[key])
|
||||
if c.ccc != ccc(d[0]) {
|
||||
// We assume the lead ccc of a decomposition !=0 in this case.
|
||||
if ccc(d[0]) == 0 {
|
||||
logger.Fatalf("Expected leading CCC to be non-zero; ccc is %d", c.ccc)
|
||||
}
|
||||
}
|
||||
} else if v := makeEntry(&f)<<8 | uint16(c.ccc); v != 0 {
|
||||
trie.insert(c.codePoint, 0x8000|v)
|
||||
}
|
||||
}
|
||||
size += trie.printTables(varnames[i])
|
||||
}
|
||||
size += nfcT.printTables("nfcDecomp")
|
||||
size += nfkcT.printTables("nfkcDecomp")
|
||||
return size
|
||||
}
|
||||
|
||||
|
@ -687,15 +728,15 @@ func makeTables() {
|
|||
}
|
||||
list := strings.Split(*tablelist, ",")
|
||||
if *tablelist == "all" {
|
||||
list = []string{"decomp", "recomp", "info"}
|
||||
list = []string{"recomp", "info"}
|
||||
}
|
||||
fmt.Printf(fileHeader, *tablelist, *url)
|
||||
|
||||
fmt.Println("// Version is the Unicode edition from which the tables are derived.")
|
||||
fmt.Printf("const Version = %q\n\n", version())
|
||||
|
||||
if contains(list, "decomp") {
|
||||
size += printDecompositionTables()
|
||||
if contains(list, "info") {
|
||||
size += printCharInfoTables()
|
||||
}
|
||||
|
||||
if contains(list, "recomp") {
|
||||
|
@ -730,9 +771,6 @@ func makeTables() {
|
|||
fmt.Printf("}\n\n")
|
||||
}
|
||||
|
||||
if contains(list, "info") {
|
||||
size += printCharInfoTables()
|
||||
}
|
||||
fmt.Printf("// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size)
|
||||
}
|
||||
|
||||
|
@ -761,6 +799,11 @@ func verifyComputed() {
|
|||
log.Fatalf("%U: NF*C must be maybe if combinesBackward", i)
|
||||
}
|
||||
}
|
||||
nfc := c.forms[FCanonical]
|
||||
nfkc := c.forms[FCompatibility]
|
||||
if nfc.combinesBackward != nfkc.combinesBackward {
|
||||
logger.Fatalf("%U: Cannot combine combinesBackward\n", c.codePoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generate test data for trie code.
|
||||
|
||||
package main
|
||||
|
|
|
@ -448,7 +448,7 @@ func decomposeToLastBoundary(rb *reorderBuffer, buf []byte) []byte {
|
|||
}
|
||||
// Check that decomposition doesn't result in overflow.
|
||||
if info.hasDecomposition() {
|
||||
dcomp := rb.f.decompose(inputBytes(buf), p-int(info.size))
|
||||
dcomp := info.decomposition()
|
||||
for i := 0; i < len(dcomp); {
|
||||
inf := rb.f.info(inputBytes(dcomp), i)
|
||||
i += int(inf.size)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Trie table generator.
|
||||
// Used by make*tables tools to generate a go file with trie data structures
|
||||
// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd
|
||||
|
||||
// Package signal implements operating system-independent signal handling.
|
||||
package signal
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// Incoming is the global signal channel.
|
||||
// All signals received by the program will be delivered to this channel.
|
||||
var Incoming <-chan os.Signal
|
||||
|
||||
func process(ch chan<- os.Signal) {
|
||||
for {
|
||||
var mask uint32 = runtime.Sigrecv()
|
||||
for sig := uint(0); sig < 32; sig++ {
|
||||
if mask&(1<<sig) != 0 {
|
||||
ch <- os.UnixSignal(sig)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
runtime.Siginit()
|
||||
ch := make(chan os.Signal) // Done here so Incoming can have type <-chan Signal
|
||||
Incoming = ch
|
||||
go process(ch)
|
||||
}
|
||||
|
||||
// BUG(rsc): This package is unavailable on Plan 9 and Windows.
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd
|
||||
|
||||
package signal
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const sighup = os.UnixSignal(syscall.SIGHUP)
|
||||
|
||||
func TestSignal(t *testing.T) {
|
||||
// Send this process a SIGHUP.
|
||||
syscall.Syscall(syscall.SYS_KILL, uintptr(syscall.Getpid()), syscall.SIGHUP, 0)
|
||||
|
||||
if sig := (<-Incoming).(os.UnixSignal); sig != sighup {
|
||||
t.Errorf("signal was %v, want %v", sig, sighup)
|
||||
}
|
||||
}
|
|
@ -17,14 +17,14 @@ import (
|
|||
const debug = false
|
||||
|
||||
type checker struct {
|
||||
fset *token.FileSet
|
||||
scanner.ErrorVector
|
||||
types map[ast.Expr]Type
|
||||
fset *token.FileSet
|
||||
errors scanner.ErrorList
|
||||
types map[ast.Expr]Type
|
||||
}
|
||||
|
||||
func (c *checker) errorf(pos token.Pos, format string, args ...interface{}) string {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
c.Error(c.fset.Position(pos), msg)
|
||||
c.errors.Add(c.fset.Position(pos), msg)
|
||||
return msg
|
||||
}
|
||||
|
||||
|
@ -221,5 +221,6 @@ func Check(fset *token.FileSet, pkg *ast.Package) (types map[ast.Expr]Type, err
|
|||
c.checkObj(obj, false)
|
||||
}
|
||||
|
||||
return c.types, c.GetError(scanner.NoMultiples)
|
||||
c.errors.RemoveMultiples()
|
||||
return c.types, c.errors.Err()
|
||||
}
|
||||
|
|
|
@ -11,12 +11,12 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/token"
|
||||
"io"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"text/scanner"
|
||||
)
|
||||
|
@ -24,7 +24,6 @@ import (
|
|||
const trace = false // set to true for debugging
|
||||
|
||||
var (
|
||||
pkgRoot = filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH)
|
||||
pkgExts = [...]string{".a", ".5", ".6", ".8"}
|
||||
)
|
||||
|
||||
|
@ -39,8 +38,12 @@ func findPkg(path string) (filename, id string) {
|
|||
var noext string
|
||||
switch path[0] {
|
||||
default:
|
||||
// "x" -> "$GOROOT/pkg/$GOOS_$GOARCH/x.ext", "x"
|
||||
noext = filepath.Join(pkgRoot, path)
|
||||
// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
|
||||
tree, pkg, err := build.FindTree(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
noext = filepath.Join(tree.PkgDir(), pkg)
|
||||
|
||||
case '.':
|
||||
// "./x" -> "/this/directory/x.ext", "/this/directory/x"
|
||||
|
|
|
@ -6,7 +6,9 @@ package types
|
|||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
@ -31,7 +33,7 @@ func init() {
|
|||
gcPath = gcName
|
||||
return
|
||||
}
|
||||
gcPath = filepath.Join(runtime.GOROOT(), "/bin/tool/", gcName)
|
||||
gcPath = filepath.Join(build.ToolDir, gcName)
|
||||
}
|
||||
|
||||
func compile(t *testing.T, dirname, filename string) {
|
||||
|
@ -61,7 +63,7 @@ func testPath(t *testing.T, path string) bool {
|
|||
const maxTime = 3 * time.Second
|
||||
|
||||
func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
|
||||
dirname := filepath.Join(pkgRoot, dir)
|
||||
dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir)
|
||||
list, err := ioutil.ReadDir(dirname)
|
||||
if err != nil {
|
||||
t.Errorf("testDir(%s): %s", dirname, err)
|
||||
|
@ -90,6 +92,13 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
|
|||
}
|
||||
|
||||
func TestGcImport(t *testing.T) {
|
||||
// On cross-compile builds, the path will not exist.
|
||||
// Need to use GOHOSTOS, which is not available.
|
||||
if _, err := os.Stat(gcPath); err != nil {
|
||||
t.Logf("skipping test: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
compile(t, "testdata", "exports.go")
|
||||
|
||||
nimports := 0
|
||||
|
|
|
@ -423,6 +423,7 @@ var fmttests = []struct {
|
|||
{"p0=%p", new(int), "p0=0xPTR"},
|
||||
{"p1=%s", &pValue, "p1=String(p)"}, // String method...
|
||||
{"p2=%p", &pValue, "p2=0xPTR"}, // ... not called with %p
|
||||
{"p3=%p", (*int)(nil), "p3=0x0"},
|
||||
{"p4=%#p", new(int), "p4=PTR"},
|
||||
|
||||
// %p on non-pointers
|
||||
|
@ -431,6 +432,14 @@ var fmttests = []struct {
|
|||
{"%p", make([]int, 1), "0xPTR"},
|
||||
{"%p", 27, "%!p(int=27)"}, // not a pointer at all
|
||||
|
||||
// %q on pointers
|
||||
{"%q", (*int)(nil), "%!q(*int=<nil>)"},
|
||||
{"%q", new(int), "%!q(*int=0xPTR)"},
|
||||
|
||||
// %v on pointers formats 0 as <nil>
|
||||
{"%v", (*int)(nil), "<nil>"},
|
||||
{"%v", new(int), "0xPTR"},
|
||||
|
||||
// %d on Stringer should give integer if possible
|
||||
{"%s", time.Time{}.Month(), "January"},
|
||||
{"%d", time.Time{}.Month(), "1"},
|
||||
|
|
|
@ -553,6 +553,14 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, depth int) {
|
|||
}
|
||||
|
||||
func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
|
||||
switch verb {
|
||||
case 'p', 'v', 'b', 'd', 'o', 'x', 'X':
|
||||
// ok
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
return
|
||||
}
|
||||
|
||||
var u uintptr
|
||||
switch value.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
|
||||
|
@ -561,6 +569,7 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
|
|||
p.badVerb(verb)
|
||||
return
|
||||
}
|
||||
|
||||
if goSyntax {
|
||||
p.add('(')
|
||||
p.buf.WriteString(value.Type().String())
|
||||
|
@ -572,6 +581,8 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
|
|||
p.fmt0x64(uint64(u), true)
|
||||
}
|
||||
p.add(')')
|
||||
} else if verb == 'v' && u == 0 {
|
||||
p.buf.Write(nilAngleBytes)
|
||||
} else {
|
||||
p.fmt0x64(uint64(u), !p.fmt.sharp)
|
||||
}
|
||||
|
@ -929,24 +940,7 @@ BigSwitch:
|
|||
break BigSwitch
|
||||
}
|
||||
}
|
||||
if goSyntax {
|
||||
p.buf.WriteByte('(')
|
||||
p.buf.WriteString(value.Type().String())
|
||||
p.buf.WriteByte(')')
|
||||
p.buf.WriteByte('(')
|
||||
if v == 0 {
|
||||
p.buf.Write(nilBytes)
|
||||
} else {
|
||||
p.fmt0x64(uint64(v), true)
|
||||
}
|
||||
p.buf.WriteByte(')')
|
||||
break
|
||||
}
|
||||
if v == 0 {
|
||||
p.buf.Write(nilAngleBytes)
|
||||
break
|
||||
}
|
||||
p.fmt0x64(uint64(v), true)
|
||||
fallthrough
|
||||
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
|
||||
p.fmtPointer(value, verb, goSyntax)
|
||||
default:
|
||||
|
|
|
@ -512,7 +512,7 @@ func (s *ss) scanBool(verb rune) bool {
|
|||
}
|
||||
return true
|
||||
case 'f', 'F':
|
||||
if s.accept("aL") && (!s.accept("lL") || !s.accept("sS") || !s.accept("eE")) {
|
||||
if s.accept("aA") && (!s.accept("lL") || !s.accept("sS") || !s.accept("eE")) {
|
||||
s.error(boolError)
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -317,6 +317,7 @@ var overflowTests = []ScanTest{
|
|||
{"(1-1e500i)", &complex128Val, 0},
|
||||
}
|
||||
|
||||
var truth bool
|
||||
var i, j, k int
|
||||
var f float64
|
||||
var s, t string
|
||||
|
@ -350,6 +351,9 @@ var multiTests = []ScanfMultiTest{
|
|||
|
||||
// Bad UTF-8: should see every byte.
|
||||
{"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""},
|
||||
|
||||
// Fixed bugs
|
||||
{"%v%v", "FALSE23", args(&truth, &i), args(false, 23), ""},
|
||||
}
|
||||
|
||||
func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, error)) {
|
||||
|
|
|
@ -14,12 +14,12 @@ import (
|
|||
)
|
||||
|
||||
type pkgBuilder struct {
|
||||
scanner.ErrorVector
|
||||
fset *token.FileSet
|
||||
fset *token.FileSet
|
||||
errors scanner.ErrorList
|
||||
}
|
||||
|
||||
func (p *pkgBuilder) error(pos token.Pos, msg string) {
|
||||
p.Error(p.fset.Position(pos), msg)
|
||||
p.errors.Add(p.fset.Position(pos), msg)
|
||||
}
|
||||
|
||||
func (p *pkgBuilder) errorf(pos token.Pos, format string, args ...interface{}) {
|
||||
|
@ -169,5 +169,6 @@ func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer,
|
|||
pkgScope.Outer = universe // reset universe scope
|
||||
}
|
||||
|
||||
return &Package{pkgName, pkgScope, imports, files}, p.GetError(scanner.Sorted)
|
||||
p.errors.Sort()
|
||||
return &Package{pkgName, pkgScope, imports, files}, p.errors.Err()
|
||||
}
|
||||
|
|
|
@ -25,10 +25,11 @@ import (
|
|||
|
||||
// A Context specifies the supporting context for a build.
|
||||
type Context struct {
|
||||
GOARCH string // target architecture
|
||||
GOOS string // target operating system
|
||||
CgoEnabled bool // whether cgo can be used
|
||||
BuildTags []string // additional tags to recognize in +build lines
|
||||
GOARCH string // target architecture
|
||||
GOOS string // target operating system
|
||||
CgoEnabled bool // whether cgo can be used
|
||||
BuildTags []string // additional tags to recognize in +build lines
|
||||
UseAllFiles bool // use files regardless of +build lines, file names
|
||||
|
||||
// By default, ScanDir uses the operating system's
|
||||
// file system calls to read directories and files.
|
||||
|
@ -225,6 +226,7 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err error) {
|
|||
|
||||
var Sfiles []string // files with ".S" (capital S)
|
||||
var di DirInfo
|
||||
var firstFile string
|
||||
imported := make(map[string][]token.Position)
|
||||
testImported := make(map[string][]token.Position)
|
||||
fset := token.NewFileSet()
|
||||
|
@ -237,7 +239,7 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err error) {
|
|||
strings.HasPrefix(name, ".") {
|
||||
continue
|
||||
}
|
||||
if !ctxt.goodOSArchFile(name) {
|
||||
if !ctxt.UseAllFiles && !ctxt.goodOSArchFile(name) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -250,12 +252,13 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err error) {
|
|||
continue
|
||||
}
|
||||
|
||||
// Look for +build comments to accept or reject the file.
|
||||
filename, data, err := ctxt.readFile(dir, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ctxt.shouldBuild(data) {
|
||||
|
||||
// Look for +build comments to accept or reject the file.
|
||||
if !ctxt.UseAllFiles && !ctxt.shouldBuild(data) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -281,9 +284,6 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err error) {
|
|||
}
|
||||
|
||||
pkg := string(pf.Name.Name)
|
||||
if pkg == "main" && di.Package != "" && di.Package != "main" {
|
||||
continue
|
||||
}
|
||||
if pkg == "documentation" {
|
||||
continue
|
||||
}
|
||||
|
@ -293,15 +293,11 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err error) {
|
|||
pkg = pkg[:len(pkg)-len("_test")]
|
||||
}
|
||||
|
||||
if pkg != di.Package && di.Package == "main" {
|
||||
// Found non-main package but was recording
|
||||
// information about package main. Reset.
|
||||
di = DirInfo{}
|
||||
}
|
||||
if di.Package == "" {
|
||||
di.Package = pkg
|
||||
firstFile = name
|
||||
} else if pkg != di.Package {
|
||||
return nil, fmt.Errorf("%s: found packages %s and %s", dir, pkg, di.Package)
|
||||
return nil, fmt.Errorf("%s: found packages %s (%s) and %s (%s)", dir, di.Package, firstFile, pkg, name)
|
||||
}
|
||||
if pf.Doc != nil {
|
||||
if di.PackageComment != nil {
|
||||
|
|
|
@ -12,6 +12,9 @@ import (
|
|||
"runtime"
|
||||
)
|
||||
|
||||
// ToolDir is the directory containing build tools.
|
||||
var ToolDir = filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
|
||||
|
||||
// Path is a validated list of Trees derived from $GOROOT and $GOPATH at init.
|
||||
var Path []*Tree
|
||||
|
||||
|
|
|
@ -14,12 +14,14 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var update = flag.Bool("update", false, "update golden (.out) files")
|
||||
var files = flag.String("files", "", "consider only Go test files matching this regular expression")
|
||||
|
||||
const dataDir = "testdata"
|
||||
|
||||
|
@ -66,14 +68,26 @@ type bundle struct {
|
|||
}
|
||||
|
||||
func test(t *testing.T, mode Mode) {
|
||||
// get all packages
|
||||
// determine file filter
|
||||
filter := isGoFile
|
||||
if *files != "" {
|
||||
rx, err := regexp.Compile(*files)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
filter = func(fi os.FileInfo) bool {
|
||||
return isGoFile(fi) && rx.MatchString(fi.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// get packages
|
||||
fset := token.NewFileSet()
|
||||
pkgs, err := parser.ParseDir(fset, dataDir, isGoFile, parser.ParseComments)
|
||||
pkgs, err := parser.ParseDir(fset, dataDir, filter, parser.ParseComments)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// test all packages
|
||||
// test packages
|
||||
for _, pkg := range pkgs {
|
||||
importpath := dataDir + "/" + pkg.Name
|
||||
doc := New(pkg, importpath, mode)
|
||||
|
|
|
@ -9,6 +9,7 @@ package doc
|
|||
import (
|
||||
"go/ast"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
@ -21,28 +22,47 @@ type Example struct {
|
|||
}
|
||||
|
||||
func Examples(pkg *ast.Package) []*Example {
|
||||
var examples []*Example
|
||||
for _, src := range pkg.Files {
|
||||
for _, decl := range src.Decls {
|
||||
var list []*Example
|
||||
for _, file := range pkg.Files {
|
||||
hasTests := false // file contains tests or benchmarks
|
||||
numDecl := 0 // number of non-import declarations in the file
|
||||
var flist []*Example
|
||||
for _, decl := range file.Decls {
|
||||
if g, ok := decl.(*ast.GenDecl); ok && g.Tok != token.IMPORT {
|
||||
numDecl++
|
||||
continue
|
||||
}
|
||||
f, ok := decl.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
numDecl++
|
||||
name := f.Name.Name
|
||||
if isTest(name, "Test") || isTest(name, "Benchmark") {
|
||||
hasTests = true
|
||||
continue
|
||||
}
|
||||
if !isTest(name, "Example") {
|
||||
continue
|
||||
}
|
||||
examples = append(examples, &Example{
|
||||
flist = append(flist, &Example{
|
||||
Name: name[len("Example"):],
|
||||
Body: &printer.CommentedNode{
|
||||
Node: f.Body,
|
||||
Comments: src.Comments,
|
||||
Comments: file.Comments,
|
||||
},
|
||||
Output: f.Doc.Text(),
|
||||
})
|
||||
}
|
||||
if !hasTests && numDecl > 1 && len(flist) == 1 {
|
||||
// If this file only has one example function, some
|
||||
// other top-level declarations, and no tests or
|
||||
// benchmarks, use the whole file as the example.
|
||||
flist[0].Body.Node = file
|
||||
}
|
||||
list = append(list, flist...)
|
||||
}
|
||||
return examples
|
||||
return list
|
||||
}
|
||||
|
||||
// isTest tells whether name looks like a test, example, or benchmark.
|
||||
|
|
|
@ -22,12 +22,38 @@ func filterIdentList(list []*ast.Ident) []*ast.Ident {
|
|||
return list[0:j]
|
||||
}
|
||||
|
||||
// removeErrorField removes anonymous fields named "error" from an interface.
|
||||
// This is called when "error" has been determined to be a local name,
|
||||
// not the predeclared type.
|
||||
//
|
||||
func removeErrorField(ityp *ast.InterfaceType) {
|
||||
list := ityp.Methods.List // we know that ityp.Methods != nil
|
||||
j := 0
|
||||
for _, field := range list {
|
||||
keepField := true
|
||||
if n := len(field.Names); n == 0 {
|
||||
// anonymous field
|
||||
if fname, _ := baseTypeName(field.Type); fname == "error" {
|
||||
keepField = false
|
||||
}
|
||||
}
|
||||
if keepField {
|
||||
list[j] = field
|
||||
j++
|
||||
}
|
||||
}
|
||||
if j < len(list) {
|
||||
ityp.Incomplete = true
|
||||
}
|
||||
ityp.Methods.List = list[0:j]
|
||||
}
|
||||
|
||||
// filterFieldList removes unexported fields (field names) from the field list
|
||||
// in place and returns true if fields were removed. Anonymous fields are
|
||||
// recorded with the parent type. filterType is called with the types of
|
||||
// all remaining fields.
|
||||
//
|
||||
func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList) (removedFields bool) {
|
||||
func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp *ast.InterfaceType) (removedFields bool) {
|
||||
if fields == nil {
|
||||
return
|
||||
}
|
||||
|
@ -37,9 +63,15 @@ func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList) (remo
|
|||
keepField := false
|
||||
if n := len(field.Names); n == 0 {
|
||||
// anonymous field
|
||||
name := r.recordAnonymousField(parent, field.Type)
|
||||
if ast.IsExported(name) {
|
||||
fname := r.recordAnonymousField(parent, field.Type)
|
||||
if ast.IsExported(fname) {
|
||||
keepField = true
|
||||
} else if ityp != nil && fname == "error" {
|
||||
// possibly the predeclared error interface; keep
|
||||
// it for now but remember this interface so that
|
||||
// it can be fixed if error is also defined locally
|
||||
keepField = true
|
||||
r.remember(ityp)
|
||||
}
|
||||
} else {
|
||||
field.Names = filterIdentList(field.Names)
|
||||
|
@ -86,14 +118,14 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) {
|
|||
case *ast.ArrayType:
|
||||
r.filterType(nil, t.Elt)
|
||||
case *ast.StructType:
|
||||
if r.filterFieldList(parent, t.Fields) {
|
||||
if r.filterFieldList(parent, t.Fields, nil) {
|
||||
t.Incomplete = true
|
||||
}
|
||||
case *ast.FuncType:
|
||||
r.filterParamList(t.Params)
|
||||
r.filterParamList(t.Results)
|
||||
case *ast.InterfaceType:
|
||||
if r.filterFieldList(parent, t.Methods) {
|
||||
if r.filterFieldList(parent, t.Methods, t) {
|
||||
t.Incomplete = true
|
||||
}
|
||||
case *ast.MapType:
|
||||
|
@ -116,9 +148,12 @@ func (r *reader) filterSpec(spec ast.Spec) bool {
|
|||
return true
|
||||
}
|
||||
case *ast.TypeSpec:
|
||||
if ast.IsExported(s.Name.Name) {
|
||||
if name := s.Name.Name; ast.IsExported(name) {
|
||||
r.filterType(r.lookupType(s.Name.Name), s.Type)
|
||||
return true
|
||||
} else if name == "error" {
|
||||
// special case: remember that error is declared locally
|
||||
r.errorDecl = true
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
The headscan command extracts comment headings from package files;
|
||||
it is used to detect false positives which may require an adjustment
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
//
|
||||
// Internally, we treat functions like methods and collect them in method sets.
|
||||
|
||||
// methodSet describes a set of methods. Entries where Decl == nil are conflict
|
||||
// A methodSet describes a set of methods. Entries where Decl == nil are conflict
|
||||
// entries (more then one method with the same name at the same embedding level).
|
||||
//
|
||||
type methodSet map[string]*Func
|
||||
|
@ -110,6 +110,9 @@ func baseTypeName(x ast.Expr) (name string, imported bool) {
|
|||
return
|
||||
}
|
||||
|
||||
// An embeddedSet describes a set of embedded types.
|
||||
type embeddedSet map[*namedType]bool
|
||||
|
||||
// A namedType represents a named unqualified (package local, or possibly
|
||||
// predeclared) type. The namedType for a type name is always found via
|
||||
// reader.lookupType.
|
||||
|
@ -119,9 +122,9 @@ type namedType struct {
|
|||
name string // type name
|
||||
decl *ast.GenDecl // nil if declaration hasn't been seen yet
|
||||
|
||||
isEmbedded bool // true if this type is embedded
|
||||
isStruct bool // true if this type is a struct
|
||||
embedded map[*namedType]bool // true if the embedded type is a pointer
|
||||
isEmbedded bool // true if this type is embedded
|
||||
isStruct bool // true if this type is a struct
|
||||
embedded embeddedSet // true if the embedded type is a pointer
|
||||
|
||||
// associated declarations
|
||||
values []*Value // consts and vars
|
||||
|
@ -152,6 +155,10 @@ type reader struct {
|
|||
values []*Value // consts and vars
|
||||
types map[string]*namedType
|
||||
funcs methodSet
|
||||
|
||||
// support for package-local error type declarations
|
||||
errorDecl bool // if set, type "error" was declared locally
|
||||
fixlist []*ast.InterfaceType // list of interfaces containing anonymous field "error"
|
||||
}
|
||||
|
||||
func (r *reader) isVisible(name string) bool {
|
||||
|
@ -173,7 +180,7 @@ func (r *reader) lookupType(name string) *namedType {
|
|||
// type not found - add one without declaration
|
||||
typ := &namedType{
|
||||
name: name,
|
||||
embedded: make(map[*namedType]bool),
|
||||
embedded: make(embeddedSet),
|
||||
funcs: make(methodSet),
|
||||
methods: make(methodSet),
|
||||
}
|
||||
|
@ -210,6 +217,10 @@ func (r *reader) readDoc(comment *ast.CommentGroup) {
|
|||
r.doc += "\n" + text
|
||||
}
|
||||
|
||||
func (r *reader) remember(typ *ast.InterfaceType) {
|
||||
r.fixlist = append(r.fixlist, typ)
|
||||
}
|
||||
|
||||
func specNames(specs []ast.Spec) []string {
|
||||
names := make([]string, 0, len(specs)) // reasonable estimate
|
||||
for _, s := range specs {
|
||||
|
@ -274,7 +285,7 @@ func (r *reader) readValue(decl *ast.GenDecl) {
|
|||
// determine values list with which to associate the Value for this decl
|
||||
values := &r.values
|
||||
const threshold = 0.75
|
||||
if domName != "" && domFreq >= int(float64(len(decl.Specs))*threshold) {
|
||||
if domName != "" && r.isVisible(domName) && domFreq >= int(float64(len(decl.Specs))*threshold) {
|
||||
// typed entries are sufficiently frequent
|
||||
if typ := r.lookupType(domName); typ != nil {
|
||||
values = &typ.values // associate with that type
|
||||
|
@ -315,7 +326,7 @@ func (r *reader) readType(decl *ast.GenDecl, spec *ast.TypeSpec) {
|
|||
return // no name or blank name - ignore the type
|
||||
}
|
||||
|
||||
// A type should be added at most once, so info.decl
|
||||
// A type should be added at most once, so typ.decl
|
||||
// should be nil - if it is not, simply overwrite it.
|
||||
typ.decl = decl
|
||||
|
||||
|
@ -543,7 +554,8 @@ func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int)
|
|||
|
||||
// collectEmbeddedMethods collects the embedded methods of typ in mset.
|
||||
//
|
||||
func (r *reader) collectEmbeddedMethods(mset methodSet, typ *namedType, recvTypeName string, embeddedIsPtr bool, level int) {
|
||||
func (r *reader) collectEmbeddedMethods(mset methodSet, typ *namedType, recvTypeName string, embeddedIsPtr bool, level int, visited embeddedSet) {
|
||||
visited[typ] = true
|
||||
for embedded, isPtr := range typ.embedded {
|
||||
// Once an embedded type is embedded as a pointer type
|
||||
// all embedded types in those types are treated like
|
||||
|
@ -557,8 +569,11 @@ func (r *reader) collectEmbeddedMethods(mset methodSet, typ *namedType, recvType
|
|||
mset.add(customizeRecv(m, recvTypeName, thisEmbeddedIsPtr, level))
|
||||
}
|
||||
}
|
||||
r.collectEmbeddedMethods(mset, embedded, recvTypeName, thisEmbeddedIsPtr, level+1)
|
||||
if !visited[embedded] {
|
||||
r.collectEmbeddedMethods(mset, embedded, recvTypeName, thisEmbeddedIsPtr, level+1, visited)
|
||||
}
|
||||
}
|
||||
delete(visited, typ)
|
||||
}
|
||||
|
||||
// computeMethodSets determines the actual method sets for each type encountered.
|
||||
|
@ -568,12 +583,19 @@ func (r *reader) computeMethodSets() {
|
|||
// collect embedded methods for t
|
||||
if t.isStruct {
|
||||
// struct
|
||||
r.collectEmbeddedMethods(t.methods, t, t.name, false, 1)
|
||||
r.collectEmbeddedMethods(t.methods, t, t.name, false, 1, make(embeddedSet))
|
||||
} else {
|
||||
// interface
|
||||
// TODO(gri) fix this
|
||||
}
|
||||
}
|
||||
|
||||
// if error was declared locally, don't treat it as exported field anymore
|
||||
if r.errorDecl {
|
||||
for _, ityp := range r.fixlist {
|
||||
removeErrorField(ityp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cleanupTypes removes the association of functions and methods with
|
||||
|
|
28
libgo/go/go/doc/testdata/b.0.golden
vendored
28
libgo/go/go/doc/testdata/b.0.golden
vendored
|
@ -11,19 +11,47 @@ FILENAMES
|
|||
testdata/b.go
|
||||
|
||||
CONSTANTS
|
||||
//
|
||||
const (
|
||||
C1 notExported = iota
|
||||
C2
|
||||
|
||||
C4
|
||||
C5
|
||||
)
|
||||
|
||||
//
|
||||
const C notExported = 0
|
||||
|
||||
//
|
||||
const Pi = 3.14 // Pi
|
||||
|
||||
|
||||
VARIABLES
|
||||
//
|
||||
var (
|
||||
U1, U2, U4, U5 notExported
|
||||
|
||||
U7 notExported = 7
|
||||
)
|
||||
|
||||
//
|
||||
var MaxInt int // MaxInt
|
||||
|
||||
//
|
||||
var V notExported
|
||||
|
||||
//
|
||||
var V1, V2, V4, V5 notExported
|
||||
|
||||
|
||||
FUNCTIONS
|
||||
//
|
||||
func F(x int) int
|
||||
|
||||
//
|
||||
func F1() notExported
|
||||
|
||||
// Always under the package functions list.
|
||||
func NotAFactory() int
|
||||
|
||||
|
|
36
libgo/go/go/doc/testdata/b.1.golden
vendored
36
libgo/go/go/doc/testdata/b.1.golden
vendored
|
@ -38,8 +38,42 @@ TYPES
|
|||
//
|
||||
func (x *T) M()
|
||||
|
||||
//
|
||||
type notExported int
|
||||
|
||||
//
|
||||
const (
|
||||
C1 notExported = iota
|
||||
C2
|
||||
c3
|
||||
C4
|
||||
C5
|
||||
)
|
||||
|
||||
//
|
||||
const C notExported = 0
|
||||
|
||||
//
|
||||
var (
|
||||
U1, U2, u3, U4, U5 notExported
|
||||
u6 notExported
|
||||
U7 notExported = 7
|
||||
)
|
||||
|
||||
//
|
||||
var V notExported
|
||||
|
||||
//
|
||||
var V1, V2, v3, V4, V5 notExported
|
||||
|
||||
//
|
||||
func F1() notExported
|
||||
|
||||
//
|
||||
func f2() notExported
|
||||
|
||||
// Should only appear if AllDecls is set.
|
||||
type uint struct{}
|
||||
type uint struct{} // overrides a predeclared type uint
|
||||
|
||||
// Associated with uint type if AllDecls is set.
|
||||
func UintFactory() uint
|
||||
|
|
28
libgo/go/go/doc/testdata/b.2.golden
vendored
28
libgo/go/go/doc/testdata/b.2.golden
vendored
|
@ -11,19 +11,47 @@ FILENAMES
|
|||
testdata/b.go
|
||||
|
||||
CONSTANTS
|
||||
//
|
||||
const (
|
||||
C1 notExported = iota
|
||||
C2
|
||||
|
||||
C4
|
||||
C5
|
||||
)
|
||||
|
||||
//
|
||||
const C notExported = 0
|
||||
|
||||
//
|
||||
const Pi = 3.14 // Pi
|
||||
|
||||
|
||||
VARIABLES
|
||||
//
|
||||
var (
|
||||
U1, U2, U4, U5 notExported
|
||||
|
||||
U7 notExported = 7
|
||||
)
|
||||
|
||||
//
|
||||
var MaxInt int // MaxInt
|
||||
|
||||
//
|
||||
var V notExported
|
||||
|
||||
//
|
||||
var V1, V2, V4, V5 notExported
|
||||
|
||||
|
||||
FUNCTIONS
|
||||
//
|
||||
func F(x int) int
|
||||
|
||||
//
|
||||
func F1() notExported
|
||||
|
||||
// Always under the package functions list.
|
||||
func NotAFactory() int
|
||||
|
||||
|
|
28
libgo/go/go/doc/testdata/b.go
vendored
28
libgo/go/go/doc/testdata/b.go
vendored
|
@ -6,6 +6,7 @@ package b
|
|||
|
||||
import "a"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Basic declarations
|
||||
|
||||
const Pi = 3.14 // Pi
|
||||
|
@ -28,3 +29,30 @@ func uintFactory() uint {}
|
|||
|
||||
// Should only appear if AllDecls is set.
|
||||
type uint struct{} // overrides a predeclared type uint
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Exported declarations associated with non-exported types must always be shown.
|
||||
|
||||
type notExported int
|
||||
|
||||
const C notExported = 0
|
||||
|
||||
const (
|
||||
C1 notExported = iota
|
||||
C2
|
||||
c3
|
||||
C4
|
||||
C5
|
||||
)
|
||||
|
||||
var V notExported
|
||||
var V1, V2, v3, V4, V5 notExported
|
||||
|
||||
var (
|
||||
U1, U2, u3, U4, U5 notExported
|
||||
u6 notExported
|
||||
U7 notExported = 7
|
||||
)
|
||||
|
||||
func F1() notExported {}
|
||||
func f2() notExported {}
|
||||
|
|
67
libgo/go/go/doc/testdata/e.0.golden
vendored
67
libgo/go/go/doc/testdata/e.0.golden
vendored
|
@ -40,3 +40,70 @@ TYPES
|
|||
T4
|
||||
}
|
||||
|
||||
//
|
||||
type U1 struct {
|
||||
*U1
|
||||
}
|
||||
|
||||
// U1.M should appear as method of U1.
|
||||
func (*U1) M()
|
||||
|
||||
//
|
||||
type U2 struct {
|
||||
*U3
|
||||
}
|
||||
|
||||
// U2.M should appear as method of U2 and as method of U3 only if ...
|
||||
func (*U2) M()
|
||||
|
||||
//
|
||||
type U3 struct {
|
||||
*U2
|
||||
}
|
||||
|
||||
// U3.N should appear as method of U3 and as method of U2 only if ...
|
||||
func (*U3) N()
|
||||
|
||||
//
|
||||
type U4 struct {
|
||||
// contains filtered or unexported fields
|
||||
}
|
||||
|
||||
// U4.M should appear as method of U4.
|
||||
func (*U4) M()
|
||||
|
||||
//
|
||||
type V1 struct {
|
||||
*V2
|
||||
*V5
|
||||
}
|
||||
|
||||
//
|
||||
type V2 struct {
|
||||
*V3
|
||||
}
|
||||
|
||||
//
|
||||
type V3 struct {
|
||||
*V4
|
||||
}
|
||||
|
||||
//
|
||||
type V4 struct {
|
||||
*V5
|
||||
}
|
||||
|
||||
// V4.M should appear as method of V2 and V3 if AllMethods is set.
|
||||
func (*V4) M()
|
||||
|
||||
//
|
||||
type V5 struct {
|
||||
*V6
|
||||
}
|
||||
|
||||
//
|
||||
type V6 struct{}
|
||||
|
||||
// V6.M should appear as method of V1 and V5 if AllMethods is set.
|
||||
func (*V6) M()
|
||||
|
||||
|
|
72
libgo/go/go/doc/testdata/e.1.golden
vendored
72
libgo/go/go/doc/testdata/e.1.golden
vendored
|
@ -42,6 +42,73 @@ TYPES
|
|||
T4
|
||||
}
|
||||
|
||||
//
|
||||
type U1 struct {
|
||||
*U1
|
||||
}
|
||||
|
||||
// U1.M should appear as method of U1.
|
||||
func (*U1) M()
|
||||
|
||||
//
|
||||
type U2 struct {
|
||||
*U3
|
||||
}
|
||||
|
||||
// U2.M should appear as method of U2 and as method of U3 only if ...
|
||||
func (*U2) M()
|
||||
|
||||
//
|
||||
type U3 struct {
|
||||
*U2
|
||||
}
|
||||
|
||||
// U3.N should appear as method of U3 and as method of U2 only if ...
|
||||
func (*U3) N()
|
||||
|
||||
//
|
||||
type U4 struct {
|
||||
*u5
|
||||
}
|
||||
|
||||
// U4.M should appear as method of U4.
|
||||
func (*U4) M()
|
||||
|
||||
//
|
||||
type V1 struct {
|
||||
*V2
|
||||
*V5
|
||||
}
|
||||
|
||||
//
|
||||
type V2 struct {
|
||||
*V3
|
||||
}
|
||||
|
||||
//
|
||||
type V3 struct {
|
||||
*V4
|
||||
}
|
||||
|
||||
//
|
||||
type V4 struct {
|
||||
*V5
|
||||
}
|
||||
|
||||
// V4.M should appear as method of V2 and V3 if AllMethods is set.
|
||||
func (*V4) M()
|
||||
|
||||
//
|
||||
type V5 struct {
|
||||
*V6
|
||||
}
|
||||
|
||||
//
|
||||
type V6 struct{}
|
||||
|
||||
// V6.M should appear as method of V1 and V5 if AllMethods is set.
|
||||
func (*V6) M()
|
||||
|
||||
//
|
||||
type t1 struct{}
|
||||
|
||||
|
@ -70,3 +137,8 @@ TYPES
|
|||
// t2.M should not appear as method in a Tx type.
|
||||
func (t2e) M()
|
||||
|
||||
//
|
||||
type u5 struct {
|
||||
*U4
|
||||
}
|
||||
|
||||
|
|
85
libgo/go/go/doc/testdata/e.2.golden
vendored
85
libgo/go/go/doc/testdata/e.2.golden
vendored
|
@ -43,3 +43,88 @@ TYPES
|
|||
// T4.M should appear as method of T5 only if AllMethods is set.
|
||||
func (*T5) M()
|
||||
|
||||
//
|
||||
type U1 struct {
|
||||
*U1
|
||||
}
|
||||
|
||||
// U1.M should appear as method of U1.
|
||||
func (*U1) M()
|
||||
|
||||
//
|
||||
type U2 struct {
|
||||
*U3
|
||||
}
|
||||
|
||||
// U2.M should appear as method of U2 and as method of U3 only if ...
|
||||
func (*U2) M()
|
||||
|
||||
// U3.N should appear as method of U3 and as method of U2 only if ...
|
||||
func (U2) N()
|
||||
|
||||
//
|
||||
type U3 struct {
|
||||
*U2
|
||||
}
|
||||
|
||||
// U2.M should appear as method of U2 and as method of U3 only if ...
|
||||
func (U3) M()
|
||||
|
||||
// U3.N should appear as method of U3 and as method of U2 only if ...
|
||||
func (*U3) N()
|
||||
|
||||
//
|
||||
type U4 struct {
|
||||
// contains filtered or unexported fields
|
||||
}
|
||||
|
||||
// U4.M should appear as method of U4.
|
||||
func (*U4) M()
|
||||
|
||||
//
|
||||
type V1 struct {
|
||||
*V2
|
||||
*V5
|
||||
}
|
||||
|
||||
// V6.M should appear as method of V1 and V5 if AllMethods is set.
|
||||
func (V1) M()
|
||||
|
||||
//
|
||||
type V2 struct {
|
||||
*V3
|
||||
}
|
||||
|
||||
// V4.M should appear as method of V2 and V3 if AllMethods is set.
|
||||
func (V2) M()
|
||||
|
||||
//
|
||||
type V3 struct {
|
||||
*V4
|
||||
}
|
||||
|
||||
// V4.M should appear as method of V2 and V3 if AllMethods is set.
|
||||
func (V3) M()
|
||||
|
||||
//
|
||||
type V4 struct {
|
||||
*V5
|
||||
}
|
||||
|
||||
// V4.M should appear as method of V2 and V3 if AllMethods is set.
|
||||
func (*V4) M()
|
||||
|
||||
//
|
||||
type V5 struct {
|
||||
*V6
|
||||
}
|
||||
|
||||
// V6.M should appear as method of V1 and V5 if AllMethods is set.
|
||||
func (V5) M()
|
||||
|
||||
//
|
||||
type V6 struct{}
|
||||
|
||||
// V6.M should appear as method of V1 and V5 if AllMethods is set.
|
||||
func (*V6) M()
|
||||
|
||||
|
|
70
libgo/go/go/doc/testdata/e.go
vendored
70
libgo/go/go/doc/testdata/e.go
vendored
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -77,3 +77,71 @@ func (*T4) M() {}
|
|||
type T5 struct {
|
||||
T4
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Recursive type declarations must not lead to endless recursion.
|
||||
|
||||
type U1 struct {
|
||||
*U1
|
||||
}
|
||||
|
||||
// U1.M should appear as method of U1.
|
||||
func (*U1) M() {}
|
||||
|
||||
type U2 struct {
|
||||
*U3
|
||||
}
|
||||
|
||||
// U2.M should appear as method of U2 and as method of U3 only if AllMethods is set.
|
||||
func (*U2) M() {}
|
||||
|
||||
type U3 struct {
|
||||
*U2
|
||||
}
|
||||
|
||||
// U3.N should appear as method of U3 and as method of U2 only if AllMethods is set.
|
||||
func (*U3) N() {}
|
||||
|
||||
type U4 struct {
|
||||
*u5
|
||||
}
|
||||
|
||||
// U4.M should appear as method of U4.
|
||||
func (*U4) M() {}
|
||||
|
||||
type u5 struct {
|
||||
*U4
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// A higher-level embedded type (and its methods) wins over the same type (and
|
||||
// its methods) embedded at a lower level.
|
||||
|
||||
type V1 struct {
|
||||
*V2
|
||||
*V5
|
||||
}
|
||||
|
||||
type V2 struct {
|
||||
*V3
|
||||
}
|
||||
|
||||
type V3 struct {
|
||||
*V4
|
||||
}
|
||||
|
||||
type V4 struct {
|
||||
*V5
|
||||
}
|
||||
|
||||
type V5 struct {
|
||||
*V6
|
||||
}
|
||||
|
||||
type V6 struct{}
|
||||
|
||||
// V4.M should appear as method of V2 and V3 if AllMethods is set.
|
||||
func (*V4) M() {}
|
||||
|
||||
// V6.M should appear as method of V1 and V5 if AllMethods is set.
|
||||
func (*V6) M() {}
|
||||
|
|
30
libgo/go/go/doc/testdata/error1.0.golden
vendored
Normal file
30
libgo/go/go/doc/testdata/error1.0.golden
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
PACKAGE error1
|
||||
|
||||
IMPORTPATH
|
||||
testdata/error1
|
||||
|
||||
FILENAMES
|
||||
testdata/error1.go
|
||||
|
||||
TYPES
|
||||
//
|
||||
type I0 interface {
|
||||
// When embedded, the predeclared error interface
|
||||
// must remain visible in interface types.
|
||||
error
|
||||
}
|
||||
|
||||
//
|
||||
type S0 struct {
|
||||
// contains filtered or unexported fields
|
||||
}
|
||||
|
||||
//
|
||||
type T0 struct {
|
||||
ExportedField interface {
|
||||
// error should be visible
|
||||
error
|
||||
}
|
||||
}
|
||||
|
32
libgo/go/go/doc/testdata/error1.1.golden
vendored
Normal file
32
libgo/go/go/doc/testdata/error1.1.golden
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
PACKAGE error1
|
||||
|
||||
IMPORTPATH
|
||||
testdata/error1
|
||||
|
||||
FILENAMES
|
||||
testdata/error1.go
|
||||
|
||||
TYPES
|
||||
//
|
||||
type I0 interface {
|
||||
// When embedded, the predeclared error interface
|
||||
// must remain visible in interface types.
|
||||
error
|
||||
}
|
||||
|
||||
//
|
||||
type S0 struct {
|
||||
// In struct types, an embedded error must only be visible
|
||||
// if AllDecls is set.
|
||||
error
|
||||
}
|
||||
|
||||
//
|
||||
type T0 struct {
|
||||
ExportedField interface {
|
||||
// error should be visible
|
||||
error
|
||||
}
|
||||
}
|
||||
|
30
libgo/go/go/doc/testdata/error1.2.golden
vendored
Normal file
30
libgo/go/go/doc/testdata/error1.2.golden
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
PACKAGE error1
|
||||
|
||||
IMPORTPATH
|
||||
testdata/error1
|
||||
|
||||
FILENAMES
|
||||
testdata/error1.go
|
||||
|
||||
TYPES
|
||||
//
|
||||
type I0 interface {
|
||||
// When embedded, the predeclared error interface
|
||||
// must remain visible in interface types.
|
||||
error
|
||||
}
|
||||
|
||||
//
|
||||
type S0 struct {
|
||||
// contains filtered or unexported fields
|
||||
}
|
||||
|
||||
//
|
||||
type T0 struct {
|
||||
ExportedField interface {
|
||||
// error should be visible
|
||||
error
|
||||
}
|
||||
}
|
||||
|
24
libgo/go/go/doc/testdata/error1.go
vendored
Normal file
24
libgo/go/go/doc/testdata/error1.go
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package error1
|
||||
|
||||
type I0 interface {
|
||||
// When embedded, the predeclared error interface
|
||||
// must remain visible in interface types.
|
||||
error
|
||||
}
|
||||
|
||||
type T0 struct {
|
||||
ExportedField interface {
|
||||
// error should be visible
|
||||
error
|
||||
}
|
||||
}
|
||||
|
||||
type S0 struct {
|
||||
// In struct types, an embedded error must only be visible
|
||||
// if AllDecls is set.
|
||||
error
|
||||
}
|
27
libgo/go/go/doc/testdata/error2.0.golden
vendored
Normal file
27
libgo/go/go/doc/testdata/error2.0.golden
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
PACKAGE error2
|
||||
|
||||
IMPORTPATH
|
||||
testdata/error2
|
||||
|
||||
FILENAMES
|
||||
testdata/error2.go
|
||||
|
||||
TYPES
|
||||
//
|
||||
type I0 interface {
|
||||
// contains filtered or unexported methods
|
||||
}
|
||||
|
||||
//
|
||||
type S0 struct {
|
||||
// contains filtered or unexported fields
|
||||
}
|
||||
|
||||
//
|
||||
type T0 struct {
|
||||
ExportedField interface {
|
||||
// contains filtered or unexported methods
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue