diff --git a/decoder.go b/decoder.go index c249208..d6ad9d5 100644 --- a/decoder.go +++ b/decoder.go @@ -273,7 +273,7 @@ func (e *Encoding) decode(dst []byte, src []byte) int { } } } - up := (*[3]byte)(unsafe.Pointer(&u)) + up := (*[4]byte)(unsafe.Pointer(&u)) switch l { case 4: if !e.pad && op-opstart+3 > dstlen { @@ -281,12 +281,8 @@ func (e *Encoding) decode(dst []byte, src []byte) int { } u = ctou32(ip) u = (e.lutXd0[byte(u)] | e.lutXd1[byte(u>>8)] | e.lutXd2[byte(u>>16)] | e.lutXd3[u>>24]) - *(*byte)(unsafe.Pointer(op)) = up[0] - op++ - *(*byte)(unsafe.Pointer(op)) = up[1] - op++ - *(*byte)(unsafe.Pointer(op)) = up[2] - op++ + putTail(op, up, 3) + op += 3 cu |= u break case 3: @@ -294,10 +290,8 @@ func (e *Encoding) decode(dst []byte, src []byte) int { return 0 } u = e.lutXd0[*(*byte)(unsafe.Pointer(ip + 0))] | e.lutXd1[*(*byte)(unsafe.Pointer(ip + 1))] | e.lutXd2[*(*byte)(unsafe.Pointer(ip + 2))] - *(*byte)(unsafe.Pointer(op)) = up[0] - op++ - *(*byte)(unsafe.Pointer(op)) = up[1] - op++ + putTail(op, up, 2) + op += 2 cu |= u break case 2: @@ -305,7 +299,7 @@ func (e *Encoding) decode(dst []byte, src []byte) int { return 0 } u = e.lutXd0[*(*byte)(unsafe.Pointer(ip + 0))] | e.lutXd1[*(*byte)(unsafe.Pointer(ip + 1))] - *(*byte)(unsafe.Pointer(op)) = up[0] + putTail(op, up, 1) op++ cu |= u break diff --git a/decoder_be.go b/decoder_be.go new file mode 100644 index 0000000..ddfe28e --- /dev/null +++ b/decoder_be.go @@ -0,0 +1,20 @@ +//go:build armbe || arm64be || mips || mips64 || mips64p32 || ppc || ppc64 || sparc || sparc64 || s390 || s390x +// +build armbe arm64be mips mips64 mips64p32 ppc ppc64 sparc sparc64 s390 s390x + +package base64 + +import "unsafe" + +func putTail(ptr uintptr, tail *[4]byte, n int) { + switch n { + case 3: + *(*byte)(unsafe.Pointer(ptr)) = tail[3] + *(*byte)(unsafe.Pointer(ptr + 1)) = tail[2] + *(*byte)(unsafe.Pointer(ptr + 2)) = tail[1] + case 2: + *(*byte)(unsafe.Pointer(ptr)) = tail[3] + *(*byte)(unsafe.Pointer(ptr + 1)) = tail[2] + case 1: + *(*byte)(unsafe.Pointer(ptr)) = tail[3] + } +} diff --git a/decoder_le.go b/decoder_le.go new file mode 100644 index 0000000..e9db958 --- /dev/null +++ b/decoder_le.go @@ -0,0 +1,20 @@ +//go:build 386 || amd64 || amd64p32 || arm || arm64 || mipsle || mis64le || mips64p32le || ppc64le || riscv || riscv64 || wasm +// +build 386 amd64 amd64p32 arm arm64 mipsle mis64le mips64p32le ppc64le riscv riscv64 wasm + +package base64 + +import "unsafe" + +func putTail(ptr uintptr, tail *[4]byte, n int) { + switch n { + case 3: + *(*byte)(unsafe.Pointer(ptr)) = tail[0] + *(*byte)(unsafe.Pointer(ptr + 1)) = tail[1] + *(*byte)(unsafe.Pointer(ptr + 2)) = tail[2] + case 2: + *(*byte)(unsafe.Pointer(ptr)) = tail[0] + *(*byte)(unsafe.Pointer(ptr + 1)) = tail[1] + case 1: + *(*byte)(unsafe.Pointer(ptr)) = tail[0] + } +} diff --git a/utils.go b/utils.go index 1257a6a..46d7f9e 100644 --- a/utils.go +++ b/utils.go @@ -2,7 +2,6 @@ package base64 import ( "math" - "math/bits" "unsafe" ) @@ -30,21 +29,6 @@ func s2b(value string) (b []byte) { return b } -//go:nosplit -func bswap32(ptr uintptr) uint32 { - return bits.ReverseBytes32(*(*uint32)(unsafe.Pointer(ptr))) -} - -//go:nosplit -func stou32(cp uintptr, x uint32) { - *(*uint32)(unsafe.Pointer(cp)) = x -} - -//go:nosplit -func ctou32(cp uintptr) uint32 { - return *(*uint32)(unsafe.Pointer(cp)) -} - func makeLuts(lutSe [64]byte) ([4096]uint32, [256]uint32, [256]uint32, [256]uint32, [256]uint32) { lutXe := [4096]uint32{} lutXd0 := [256]uint32{} diff --git a/utils_be.go b/utils_be.go new file mode 100644 index 0000000..2cbc6a2 --- /dev/null +++ b/utils_be.go @@ -0,0 +1,24 @@ +//go:build armbe || arm64be || mips || mips64 || mips64p32 || ppc || ppc64 || sparc || sparc64 || s390 || s390x +// +build armbe arm64be mips mips64 mips64p32 ppc ppc64 sparc sparc64 s390 s390x + +package base64 + +import ( + "math/bits" + "unsafe" +) + +//go:nosplit +func bswap32(ptr uintptr) uint32 { + return *(*uint32)(unsafe.Pointer(ptr)) +} + +//go:nosplit +func stou32(cp uintptr, x uint32) { + *(*uint32)(unsafe.Pointer(cp)) = bits.ReverseBytes32(x) +} + +//go:nosplit +func ctou32(cp uintptr) uint32 { + return bits.ReverseBytes32(*(*uint32)(unsafe.Pointer(cp))) +} diff --git a/utils_le.go b/utils_le.go new file mode 100644 index 0000000..53c30b7 --- /dev/null +++ b/utils_le.go @@ -0,0 +1,24 @@ +//go:build 386 || amd64 || amd64p32 || arm || arm64 || mipsle || mis64le || mips64p32le || ppc64le || riscv || riscv64 || wasm +// +build 386 amd64 amd64p32 arm arm64 mipsle mis64le mips64p32le ppc64le riscv riscv64 wasm + +package base64 + +import ( + "math/bits" + "unsafe" +) + +//go:nosplit +func bswap32(ptr uintptr) uint32 { + return bits.ReverseBytes32(*(*uint32)(unsafe.Pointer(ptr))) +} + +//go:nosplit +func stou32(cp uintptr, x uint32) { + *(*uint32)(unsafe.Pointer(cp)) = x +} + +//go:nosplit +func ctou32(cp uintptr) uint32 { + return *(*uint32)(unsafe.Pointer(cp)) +}