// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package git85 implements the radix 85 data encoding
// used in the GIT version control system.
package git85

import (
	"bytes";
	"io";
	"os";
	"strconv";
)

type CorruptInputError int64

func (e CorruptInputError) String() string {
	return "illegal git85 data at input byte" + strconv.Itoa64(int64(e))
}

const encode = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"

// The decodings are 1+ the actual value, so that the
// default zero value can be used to mean "not valid".
var decode = [256]uint8{
	'0': 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
	'A': 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
	24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
	'a': 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
	50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
	'!': 63,
	'#': 64, 65, 66, 67,
	'(': 68, 69, 70, 71,
	'-': 72,
	';': 73,
	'<': 74, 75, 76, 77,
	'@': 78,
	'^': 79, 80, 81,
	'{': 82, 83, 84, 85,
}

// Encode encodes src into EncodedLen(len(src))
// bytes of dst.  As a convenience, it returns the number
// of bytes written to dst, but this value is always EncodedLen(len(src)).
// Encode implements the radix 85 encoding used in the
// GIT version control tool.
//
// The encoding splits src into chunks of at most 52 bytes
// and encodes each chunk on its own line.
func Encode(dst, src []byte) int {
	ndst := 0;
	for len(src) > 0 {
		n := len(src);
		if n > 52 {
			n = 52
		}
		if n <= 27 {
			dst[ndst] = byte('A' + n - 1)
		} else {
			dst[ndst] = byte('a' + n - 26 - 1)
		}
		ndst++;
		for i := 0; i < n; i += 4 {
			var v uint32;
			for j := 0; j < 4 && i+j < n; j++ {
				v |= uint32(src[i+j]) << uint(24-j*8)
			}
			for j := 4; j >= 0; j-- {
				dst[ndst+j] = encode[v%85];
				v /= 85;
			}
			ndst += 5;
		}
		dst[ndst] = '\n';
		ndst++;
		src = src[n:len(src)];
	}
	return ndst;
}

// EncodedLen returns the length of an encoding of n source bytes.
func EncodedLen(n int) int {
	if n == 0 {
		return 0
	}
	// 5 bytes per 4 bytes of input, rounded up.
	// 2 extra bytes for each line of 52 src bytes, rounded up.
	return (n+3)/4*5 + (n+51)/52*2;
}

var newline = []byte{'\n'}

// Decode decodes src into at most MaxDecodedLen(len(src))
// bytes, returning the actual number of bytes written to dst.
//
// If Decode encounters invalid input, it returns a CorruptInputError.
//
func Decode(dst, src []byte) (n int, err os.Error) {
	ndst := 0;
	nsrc := 0;
	for nsrc < len(src) {
		var l int;
		switch ch := int(src[nsrc]); {
		case 'A' <= ch && ch <= 'Z':
			l = ch - 'A' + 1
		case 'a' <= ch && ch <= 'z':
			l = ch - 'a' + 26 + 1
		default:
			return ndst, CorruptInputError(nsrc)
		}
		if nsrc+1+l > len(src) {
			return ndst, CorruptInputError(nsrc)
		}
		el := (l + 3) / 4 * 5;	// encoded len
		if nsrc+1+el+1 > len(src) || src[nsrc+1+el] != '\n' {
			return ndst, CorruptInputError(nsrc)
		}
		line := src[nsrc+1 : nsrc+1+el];
		for i := 0; i < el; i += 5 {
			var v uint32;
			for j := 0; j < 5; j++ {
				ch := decode[line[i+j]];
				if ch == 0 {
					return ndst, CorruptInputError(nsrc + 1 + i + j)
				}
				v = v*85 + uint32(ch-1);
			}
			for j := 0; j < 4; j++ {
				dst[ndst] = byte(v >> 24);
				v <<= 8;
				ndst++;
			}
		}
		// Last fragment may have run too far (but there was room in dst).
		// Back up.
		if l%4 != 0 {
			ndst -= 4 - l%4
		}
		nsrc += 1 + el + 1;
	}
	return ndst, nil;
}

func MaxDecodedLen(n int) int	{ return n / 5 * 4 }

// NewEncoder returns a new GIT base85 stream encoder.  Data written to
// the returned writer will be encoded and then written to w.
// The GIT encoding operates on 52-byte blocks; when finished
// writing, the caller must Close the returned encoder to flush any
// partially written blocks.
func NewEncoder(w io.Writer) io.WriteCloser	{ return &encoder{w: w} }

type encoder struct {
	w	io.Writer;
	err	os.Error;
	buf	[52]byte;
	nbuf	int;
	out	[1024]byte;
	nout	int;
}

func (e *encoder) Write(p []byte) (n int, err os.Error) {
	if e.err != nil {
		return 0, e.err
	}

	// Leading fringe.
	if e.nbuf > 0 {
		var i int;
		for i = 0; i < len(p) && e.nbuf < 52; i++ {
			e.buf[e.nbuf] = p[i];
			e.nbuf++;
		}
		n += i;
		p = p[i:len(p)];
		if e.nbuf < 52 {
			return
		}
		nout := Encode(&e.out, &e.buf);
		if _, e.err = e.w.Write(e.out[0:nout]); e.err != nil {
			return n, e.err
		}
		e.nbuf = 0;
	}

	// Large interior chunks.
	for len(p) >= 52 {
		nn := len(e.out) / (1 + 52/4*5 + 1) * 52;
		if nn > len(p) {
			nn = len(p) / 52 * 52
		}
		if nn > 0 {
			nout := Encode(&e.out, p[0:nn]);
			if _, e.err = e.w.Write(e.out[0:nout]); e.err != nil {
				return n, e.err
			}
		}
		n += nn;
		p = p[nn:len(p)];
	}

	// Trailing fringe.
	for i := 0; i < len(p); i++ {
		e.buf[i] = p[i]
	}
	e.nbuf = len(p);
	n += len(p);
	return;
}

func (e *encoder) Close() os.Error {
	// If there's anything left in the buffer, flush it out
	if e.err == nil && e.nbuf > 0 {
		nout := Encode(&e.out, e.buf[0:e.nbuf]);
		e.nbuf = 0;
		_, e.err = e.w.Write(e.out[0:nout]);
	}
	return e.err;
}

// NewDecoder returns a new GIT base85 stream decoder.
func NewDecoder(r io.Reader) io.Reader	{ return &decoder{r: r} }

type decoder struct {
	r	io.Reader;
	err	os.Error;
	readErr	os.Error;
	buf	[1024]byte;
	nbuf	int;
	out	[]byte;
	outbuf	[1024]byte;
	off	int64;
}

func (d *decoder) Read(p []byte) (n int, err os.Error) {
	if len(p) == 0 {
		return 0, nil
	}

	for {
		// Copy leftover output from last decode.
		if len(d.out) > 0 {
			n = bytes.Copy(p, d.out);
			d.out = d.out[n:len(d.out)];
			return;
		}

		// Out of decoded output.  Check errors.
		if d.err != nil {
			return 0, d.err
		}
		if d.readErr != nil {
			d.err = d.readErr;
			return 0, d.err;
		}

		// Read and decode more input.
		var nn int;
		nn, d.readErr = d.r.Read(d.buf[d.nbuf:len(d.buf)]);
		d.nbuf += nn;

		// Send complete lines to Decode.
		nl := bytes.LastIndex(d.buf[0:d.nbuf], newline);
		if nl < 0 {
			continue
		}
		nn, d.err = Decode(&d.outbuf, d.buf[0:nl+1]);
		if e, ok := d.err.(CorruptInputError); ok {
			d.err = CorruptInputError(int64(e) + d.off)
		}
		d.out = d.outbuf[0:nn];
		d.nbuf = bytes.Copy(&d.buf, d.buf[nl+1:d.nbuf]);
		d.off += int64(nl + 1);
	}
	panic("unreacahable");
}
