// 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(src, dst []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(src, dst []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.buf, &e.out);
		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(p[0:nn], &e.out);
			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.buf[0:e.nbuf], &e.out);
		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.buf[0:nl+1], &d.outbuf);
		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");
}

