master
 1package gitdiff
 2
 3import (
 4	"fmt"
 5)
 6
 7var (
 8	b85Table map[byte]byte
 9	b85Alpha = []byte(
10		"0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "!#$%&()*+-;<=>?@^_`{|}~",
11	)
12)
13
14func init() {
15	b85Table = make(map[byte]byte)
16	for i, c := range b85Alpha {
17		b85Table[c] = byte(i)
18	}
19}
20
21// base85Decode decodes Base85-encoded data from src into dst. It uses the
22// alphabet defined by base85.c in the Git source tree. src must contain at
23// least len(dst) bytes of encoded data.
24func base85Decode(dst, src []byte) error {
25	var v uint32
26	var n, ndst int
27	for i, b := range src {
28		if b, ok := b85Table[b]; ok {
29			v = 85*v + uint32(b)
30			n++
31		} else {
32			return fmt.Errorf("invalid base85 byte at index %d: 0x%X", i, src[i])
33		}
34		if n == 5 {
35			rem := len(dst) - ndst
36			for j := 0; j < 4 && j < rem; j++ {
37				dst[ndst] = byte(v >> 24)
38				ndst++
39				v <<= 8
40			}
41			v = 0
42			n = 0
43		}
44	}
45	if n > 0 {
46		return fmt.Errorf("base85 data terminated by underpadded sequence")
47	}
48	if ndst < len(dst) {
49		return fmt.Errorf("base85 data underrun: %d < %d", ndst, len(dst))
50	}
51	return nil
52}
53
54// base85Encode encodes src in Base85, writing the result to dst. It uses the
55// alphabet defined by base85.c in the Git source tree.
56func base85Encode(dst, src []byte) {
57	var di, si int
58
59	encode := func(v uint32) {
60		dst[di+0] = b85Alpha[(v/(85*85*85*85))%85]
61		dst[di+1] = b85Alpha[(v/(85*85*85))%85]
62		dst[di+2] = b85Alpha[(v/(85*85))%85]
63		dst[di+3] = b85Alpha[(v/85)%85]
64		dst[di+4] = b85Alpha[v%85]
65	}
66
67	n := (len(src) / 4) * 4
68	for si < n {
69		encode(uint32(src[si+0])<<24 | uint32(src[si+1])<<16 | uint32(src[si+2])<<8 | uint32(src[si+3]))
70		si += 4
71		di += 5
72	}
73
74	var v uint32
75	switch len(src) - si {
76	case 3:
77		v |= uint32(src[si+2]) << 8
78		fallthrough
79	case 2:
80		v |= uint32(src[si+1]) << 16
81		fallthrough
82	case 1:
83		v |= uint32(src[si+0]) << 24
84		encode(v)
85	}
86}
87
88// base85Len returns the length of n bytes of Base85 encoded data.
89func base85Len(n int) int {
90	return (n + 3) / 4 * 5
91}