<commit_before>package lzma

import (
	"io"
)

// Maximum and minimum values for individual properties.
const (
	MinLC       = 0
	MaxLC       = 8
	MinLP       = 0
	MaxLP       = 4
	MinPB       = 0
	MaxPB       = 4
	MinDictSize = 1 << 12
	MaxDictSize = 1<<32 - 1
)

// Properties are the parameters of an LZMA stream.
//
// The dictSize will be limited by MaxInt32 on 32-bit platforms.
type Properties struct {
	// number of literal context bits
	LC int
	// number of literal position bits
	LP int
	// number of position bits
	PB int
	// size of the dictionary in bytes
	DictSize uint32
	// size of uncompressed data
	Size int64
	// header includes unpacked size
	SizeInHeader bool
	// end-of-stream marker requested
	EOS bool
}

// verifyProperties checks properties for errors.
func verifyProperties(p *Properties) error {
	if p == nil {
		return newError("properties must be non-nil")
	}
	if !(MinLC <= p.LC && p.LC <= MaxLC) {
		return newError("LC out of range")
	}
	if !(MinLP <= p.LP && p.LP <= MaxLP) {
		return newError("LP out of range")
	}
	if !(MinPB <= p.PB && p.PB <= MaxPB) {
		return newError("PB out ouf range")
	}
	if !(MinDictSize <= p.DictSize && p.DictSize <= MaxDictSize) {
		return newError("DictSize out of range")
	}
	hlen := int(p.DictSize)
	if hlen < 0 {
		return newError("DictSize cannot be converted into int")
	}
	if p.Size < 0 {
		return newError("length must not be negative")
	}
	return nil
}

// getUint32LE reads an uint32 integer from a byte slize
func getUint32LE(b []byte) uint32 {
	x := uint32(b[3]) << 24
	x |= uint32(b[2]) << 16
	x |= uint32(b[1]) << 8
	x |= uint32(b[0])
	return x
}

// getUint64LE converts the uint64 value stored as little endian to an uint64
// value.
func getUint64LE(b []byte) uint64 {
	x := uint64(b[7]) << 56
	x |= uint64(b[6]) << 48
	x |= uint64(b[5]) << 40
	x |= uint64(b[4]) << 32
	x |= uint64(b[3]) << 24
	x |= uint64(b[2]) << 16
	x |= uint64(b[1]) << 8
	x |= uint64(b[0])
	return x
}

// putUint32LE puts an uint32 integer into a byte slice that must have at least
// a lenght of 4 bytes.
func putUint32LE(b []byte, x uint32) {
	b[0] = byte(x)
	b[1] = byte(x >> 8)
	b[2] = byte(x >> 16)
	b[3] = byte(x >> 24)
}

// putUint64LE puts the uint64 value into the byte slice as little endian
// value. The byte slice b must have at least place for 8 bytes.
func putUint64LE(b []byte, x uint64) {
	b[0] = byte(x)
	b[1] = byte(x >> 8)
	b[2] = byte(x >> 16)
	b[3] = byte(x >> 24)
	b[4] = byte(x >> 32)
	b[5] = byte(x >> 40)
	b[6] = byte(x >> 48)
	b[7] = byte(x >> 56)
}

// readHeader reads the classic LZMA header.
func readHeader(r io.Reader) (p *Properties, err error) {
	b := make([]byte, 13)
	_, err = io.ReadFull(r, b)
	if err != nil {
		return nil, err
	}
	p = new(Properties)
	x := int(b[0])
	p.LC = x % 9
	x /= 9
	p.LP = x % 5
	p.PB = x / 5
	if !(MinPB <= p.PB && p.PB <= MaxPB) {
		return nil, newError("PB out of range")
	}
	p.DictSize = getUint32LE(b[1:])
	if p.DictSize < MinDictSize {
		// The LZMA specification makes the following recommendation.
		p.DictSize = MinDictSize
	}
	u := getUint64LE(b[5:])
	if u == noHeaderLen {
		p.Size = 0
		p.EOS = true
		p.SizeInHeader = false
		return p, nil
	}
	p.Size = int64(u)
	if p.Size < 0 {
		return nil, newError(
			"unpack length in header not supported by int64")
	}
	p.EOS = false
	p.SizeInHeader = true
	return p, nil
}

// writeHeader writes the header for classic LZMA files.
func writeHeader(w io.Writer, p *Properties) error {
	var err error
	if err = verifyProperties(p); err != nil {
		return err
	}
	b := make([]byte, 13)
	b[0] = byte((p.PB*5+p.LP)*9 + p.LC)
	putUint32LE(b[1:5], p.DictSize)
	var l uint64
	if p.SizeInHeader {
		l = uint64(p.Size)
	} else {
		l = noHeaderLen
	}
	putUint64LE(b[5:], l)
	_, err = w.Write(b)
	return err
}
<commit_msg>lzma: make sure that properties.Size is in bytes  Please enter the commit message for your changes. Lines starting<commit_after>package lzma

import (
	"io"
)

// Maximum and minimum values for individual properties.
const (
	MinLC       = 0
	MaxLC       = 8
	MinLP       = 0
	MaxLP       = 4
	MinPB       = 0
	MaxPB       = 4
	MinDictSize = 1 << 12
	MaxDictSize = 1<<32 - 1
)

// Properties are the parameters of an LZMA stream.
//
// The dictSize will be limited by MaxInt32 on 32-bit platforms.
type Properties struct {
	// number of literal context bits
	LC int
	// number of literal position bits
	LP int
	// number of position bits
	PB int
	// size of the dictionary in bytes
	DictSize uint32
	// size of uncompressed data in bytes
	Size int64
	// header includes unpacked size
	SizeInHeader bool
	// end-of-stream marker requested
	EOS bool
}

// verifyProperties checks properties for errors.
func verifyProperties(p *Properties) error {
	if p == nil {
		return newError("properties must be non-nil")
	}
	if !(MinLC <= p.LC && p.LC <= MaxLC) {
		return newError("LC out of range")
	}
	if !(MinLP <= p.LP && p.LP <= MaxLP) {
		return newError("LP out of range")
	}
	if !(MinPB <= p.PB && p.PB <= MaxPB) {
		return newError("PB out ouf range")
	}
	if !(MinDictSize <= p.DictSize && p.DictSize <= MaxDictSize) {
		return newError("DictSize out of range")
	}
	hlen := int(p.DictSize)
	if hlen < 0 {
		return newError("DictSize cannot be converted into int")
	}
	if p.Size < 0 {
		return newError("length must not be negative")
	}
	return nil
}

// getUint32LE reads an uint32 integer from a byte slize
func getUint32LE(b []byte) uint32 {
	x := uint32(b[3]) << 24
	x |= uint32(b[2]) << 16
	x |= uint32(b[1]) << 8
	x |= uint32(b[0])
	return x
}

// getUint64LE converts the uint64 value stored as little endian to an uint64
// value.
func getUint64LE(b []byte) uint64 {
	x := uint64(b[7]) << 56
	x |= uint64(b[6]) << 48
	x |= uint64(b[5]) << 40
	x |= uint64(b[4]) << 32
	x |= uint64(b[3]) << 24
	x |= uint64(b[2]) << 16
	x |= uint64(b[1]) << 8
	x |= uint64(b[0])
	return x
}

// putUint32LE puts an uint32 integer into a byte slice that must have at least
// a lenght of 4 bytes.
func putUint32LE(b []byte, x uint32) {
	b[0] = byte(x)
	b[1] = byte(x >> 8)
	b[2] = byte(x >> 16)
	b[3] = byte(x >> 24)
}

// putUint64LE puts the uint64 value into the byte slice as little endian
// value. The byte slice b must have at least place for 8 bytes.
func putUint64LE(b []byte, x uint64) {
	b[0] = byte(x)
	b[1] = byte(x >> 8)
	b[2] = byte(x >> 16)
	b[3] = byte(x >> 24)
	b[4] = byte(x >> 32)
	b[5] = byte(x >> 40)
	b[6] = byte(x >> 48)
	b[7] = byte(x >> 56)
}

// readHeader reads the classic LZMA header.
func readHeader(r io.Reader) (p *Properties, err error) {
	b := make([]byte, 13)
	_, err = io.ReadFull(r, b)
	if err != nil {
		return nil, err
	}
	p = new(Properties)
	x := int(b[0])
	p.LC = x % 9
	x /= 9
	p.LP = x % 5
	p.PB = x / 5
	if !(MinPB <= p.PB && p.PB <= MaxPB) {
		return nil, newError("PB out of range")
	}
	p.DictSize = getUint32LE(b[1:])
	if p.DictSize < MinDictSize {
		// The LZMA specification makes the following recommendation.
		p.DictSize = MinDictSize
	}
	u := getUint64LE(b[5:])
	if u == noHeaderLen {
		p.Size = 0
		p.EOS = true
		p.SizeInHeader = false
		return p, nil
	}
	p.Size = int64(u)
	if p.Size < 0 {
		return nil, newError(
			"unpack length in header not supported by int64")
	}
	p.EOS = false
	p.SizeInHeader = true
	return p, nil
}

// writeHeader writes the header for classic LZMA files.
func writeHeader(w io.Writer, p *Properties) error {
	var err error
	if err = verifyProperties(p); err != nil {
		return err
	}
	b := make([]byte, 13)
	b[0] = byte((p.PB*5+p.LP)*9 + p.LC)
	putUint32LE(b[1:5], p.DictSize)
	var l uint64
	if p.SizeInHeader {
		l = uint64(p.Size)
	} else {
		l = noHeaderLen
	}
	putUint64LE(b[5:], l)
	_, err = w.Write(b)
	return err
}
<|endoftext|>


<commit_before>// Copyright 2015 Ulrich Kunitz. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package lzma

import (
	"io"
)

// byteWriteCounter is a ByteWriter that counts the bytes written.
type byteWriteCounter interface {
	io.ByteWriter
	Size() int64
}

// bwCounter provides a byteWriteCounter using a ByteWriter.
type bwCounter struct {
	BW io.ByteWriter
	N  int64
}

// newBWCounter converts a ByteWriter to a byteWriteCounter.
func newBWCounter(bw io.ByteWriter) *bwCounter {
	return &bwCounter{BW: bw}
}

// WriteByte writes a single byte to the bwCounter.
func (bwc *bwCounter) WriteByte(c byte) error {
	err := bwc.BW.WriteByte(c)
	if err == nil {
		bwc.N++
	}
	return err
}

// Size returns the number of bytes written.
func (bwc *bwCounter) Size() int64 { return bwc.N }

// wCounter implements a byteWriteCounter on top of a Writer.
type wCounter struct {
	W io.Writer
	N int64
	a []byte
}

// newWCounter converts a Writer to a wCounter.
func newWCounter(w io.Writer) *wCounter {
	return &wCounter{W: w, a: make([]byte, 1)}
}

// WriteByte writes a single byte into the wCounter.
func (wc *wCounter) WriteByte(c byte) error {
	wc.a[0] = c
	n, err := wc.W.Write(wc.a)
	switch {
	case n > 1:
		panic("n > 1 for writing a single byte")
	case n == 1:
		wc.N++
		return nil
	case err == nil:
		panic("no error for n == 0")
	}
	return err
}

// Size returns the total number of bytes written.
func (wc *wCounter) Size() int64 { return wc.N }

// newByteWriteCounter transforms an io.Writer into an byteWriteCounter
func newByteWriteCounter(w io.Writer) byteWriteCounter {
	if bw, ok := w.(io.ByteWriter); ok {
		return newBWCounter(bw)
	}
	return newWCounter(w)
}

// bReader is used to convert an io.Reader into an io.ByteReader.
type bReader struct {
	io.Reader
	a []byte
}

// newByteReader transforms an io.Reader into an io.ByteReader.
func newByteReader(r io.Reader) io.ByteReader {
	if b, ok := r.(io.ByteReader); ok {
		return b
	}
	return &bReader{r, make([]byte, 1)}
}

// ReadByte reads a byte from the wrapped io.ByteReader.
func (b bReader) ReadByte() (byte, error) {
	n, err := b.Read(b.a)
	switch {
	case n > 1:
		panic("n < 1 for reading a single byte")
	case n == 1:
		return b.a[0], nil
	}
	return 0, err
}

// rangeEncoder implements range encoding of single bits. The low value can
// overflow therefore we need uint64. The cache value is used to handle
// overflows.
type rangeEncoder struct {
	w         byteWriteCounter
	nrange    uint32
	low       uint64
	cacheSize int64
	cache     byte
}

// newRangeEncoder creates a new range encoder.
func newRangeEncoder(w io.Writer) *rangeEncoder {
	return &rangeEncoder{
		w:         newByteWriteCounter(w),
		nrange:    0xffffffff,
		cacheSize: 1}
}

// DirectEncodeBit encodes the least-significant bit of b with probability 1/2.
func (e *rangeEncoder) DirectEncodeBit(b uint32) error {
	// e.bitCounter++
	e.nrange >>= 1
	e.low += uint64(e.nrange) & (0 - (uint64(b) & 1))
	if err := e.normalize(); err != nil {
		return err
	}

	return nil
}

// EncodeBit encodes the least significant bit of b. The p value will be
// updated by the function depending on the bit encoded.
func (e *rangeEncoder) EncodeBit(b uint32, p *prob) error {
	// e.bitCounter++
	bound := p.bound(e.nrange)
	if b&1 == 0 {
		e.nrange = bound
		p.inc()
	} else {
		e.low += uint64(bound)
		e.nrange -= bound
		p.dec()
	}
	if err := e.normalize(); err != nil {
		return err
	}

	return nil
}

// closeLen returns the number of bytes required for closing.
func (e *rangeEncoder) closeLen() int64 {
	return e.cacheSize + 4
}

// Close writes a complete copy of the low value.
func (e *rangeEncoder) Close() error {
	for i := 0; i < 5; i++ {
		if err := e.shiftLow(); err != nil {
			return err
		}
	}
	return nil
}

// newRangeDecoder initializes a range decoder. It reads five bytes from the
// reader and therefore may return an error.
func newRangeDecoder(r io.Reader) (d *rangeDecoder, err error) {
	d = &rangeDecoder{r: newByteReader(r)}
	err = d.init()
	return
}

// possiblyAtEnd checks whether the decoder may be at the end of the stream.
func (d *rangeDecoder) possiblyAtEnd() bool {
	return d.code == 0
}

// DirectDecodeBit decodes a bit with probability 1/2. The return value b will
// contain the bit at the least-significant position. All other bits will be
// zero.
func (d *rangeDecoder) DirectDecodeBit() (b uint32, err error) {
	// d.bitCounter++
	d.nrange >>= 1
	d.code -= d.nrange
	t := 0 - (d.code >> 31)
	d.code += d.nrange & t

	// d.code will stay less then d.nrange

	if err = d.normalize(); err != nil {
		return 0, err
	}

	b = (t + 1) & 1

	return b, nil
}

// decodeBit decodes a single bit. The bit will be returned at the
// least-significant position. All other bits will be zero. The probability
// value will be updated.
func (d *rangeDecoder) DecodeBit(p *prob) (b uint32, err error) {
	// d.bitCounter++
	bound := p.bound(d.nrange)
	if d.code < bound {
		d.nrange = bound
		p.inc()
		b = 0
	} else {
		d.code -= bound
		d.nrange -= bound
		p.dec()
		b = 1
	}

	// d.code will stay less then d.nrange

	if err = d.normalize(); err != nil {
		return 0, err
	}

	return b, nil
}

// shiftLow shifts the low value for 8 bit. The shifted byte is written into
// the byte writer. The cache value is used to handle overflows.
func (e *rangeEncoder) shiftLow() error {
	if uint32(e.low) < 0xff000000 || (e.low>>32) != 0 {
		tmp := e.cache
		for {
			err := e.w.WriteByte(tmp + byte(e.low>>32))
			if err != nil {
				return err
			}
			tmp = 0xff
			e.cacheSize--
			if e.cacheSize <= 0 {
				if e.cacheSize < 0 {
					return negError{"cacheSize", e.cacheSize}
				}
				break
			}
		}
		e.cache = byte(uint32(e.low) >> 24)
	}
	e.cacheSize++
	e.low = uint64(uint32(e.low) << 8)
	return nil
}

// normalize handles shifts of nrange and low.
func (e *rangeEncoder) normalize() error {
	const top = 1 << 24
	if e.nrange >= top {
		return nil
	}
	e.nrange <<= 8
	return e.shiftLow()
}

// rangeDecoder decodes single bits of the range encoding stream.
type rangeDecoder struct {
	r      io.ByteReader
	nrange uint32
	code   uint32
}

// init initializes the range decoder, by reading from the byte reader.
func (d *rangeDecoder) init() error {
	d.nrange = 0xffffffff
	d.code = 0

	b, err := d.r.ReadByte()
	if err != nil {
		return err
	}
	if b != 0 {
		return lzmaError{"first byte not zero"}
	}

	for i := 0; i < 4; i++ {
		if err = d.updateCode(); err != nil {
			return err
		}
	}

	if d.code >= d.nrange {
		return lzmaError{"newRangeDecoder: d.code >= d.nrange"}
	}

	return nil
}

// updateCode reads a new byte into the code.
func (d *rangeDecoder) updateCode() error {
	b, err := d.r.ReadByte()
	if err != nil {
		return err
	}
	d.code = (d.code << 8) | uint32(b)
	return nil
}

// normalize the top value and update the code value.
func (d *rangeDecoder) normalize() error {
	// assume d.code < d.nrange
	const top = 1 << 24
	if d.nrange < top {
		d.nrange <<= 8
		// d.code < d.nrange will be maintained
		if err := d.updateCode(); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>lzma: rangeEncoder supports now Len and CloseLen methods<commit_after>// Copyright 2015 Ulrich Kunitz. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package lzma

import (
	"io"
)

// byteWriteCounter is a ByteWriter that counts the bytes written.
type byteWriteCounter interface {
	io.ByteWriter
	Len() int64
}

// bwCounter provides a byteWriteCounter using a ByteWriter.
type bwCounter struct {
	BW io.ByteWriter
	N  int64
}

// newBWCounter converts a ByteWriter to a byteWriteCounter.
func newBWCounter(bw io.ByteWriter) *bwCounter {
	return &bwCounter{BW: bw}
}

// WriteByte writes a single byte to the bwCounter.
func (bwc *bwCounter) WriteByte(c byte) error {
	err := bwc.BW.WriteByte(c)
	if err == nil {
		bwc.N++
	}
	return err
}

// Len returns the number of bytes written.
func (bwc *bwCounter) Len() int64 { return bwc.N }

// wCounter implements a byteWriteCounter on top of a Writer.
type wCounter struct {
	W io.Writer
	N int64
	a []byte
}

// newWCounter converts a Writer to a wCounter.
func newWCounter(w io.Writer) *wCounter {
	return &wCounter{W: w, a: make([]byte, 1)}
}

// WriteByte writes a single byte into the wCounter.
func (wc *wCounter) WriteByte(c byte) error {
	wc.a[0] = c
	n, err := wc.W.Write(wc.a)
	switch {
	case n > 1:
		panic("n > 1 for writing a single byte")
	case n == 1:
		wc.N++
		return nil
	case err == nil:
		panic("no error for n == 0")
	}
	return err
}

// Len returns the total number of bytes written.
func (wc *wCounter) Len() int64 { return wc.N }

// newByteWriteCounter transforms an io.Writer into an byteWriteCounter
func newByteWriteCounter(w io.Writer) byteWriteCounter {
	if bw, ok := w.(io.ByteWriter); ok {
		return newBWCounter(bw)
	}
	return newWCounter(w)
}

// bReader is used to convert an io.Reader into an io.ByteReader.
type bReader struct {
	io.Reader
	a []byte
}

// newByteReader transforms an io.Reader into an io.ByteReader.
func newByteReader(r io.Reader) io.ByteReader {
	if b, ok := r.(io.ByteReader); ok {
		return b
	}
	return &bReader{r, make([]byte, 1)}
}

// ReadByte reads a byte from the wrapped io.ByteReader.
func (b bReader) ReadByte() (byte, error) {
	n, err := b.Read(b.a)
	switch {
	case n > 1:
		panic("n < 1 for reading a single byte")
	case n == 1:
		return b.a[0], nil
	}
	return 0, err
}

// rangeEncoder implements range encoding of single bits. The low value can
// overflow therefore we need uint64. The cache value is used to handle
// overflows.
type rangeEncoder struct {
	w         byteWriteCounter
	nrange    uint32
	low       uint64
	cacheSize int64
	cache     byte
}

// newRangeEncoder creates a new range encoder.
func newRangeEncoder(w io.Writer) *rangeEncoder {
	return &rangeEncoder{
		w:         newByteWriteCounter(w),
		nrange:    0xffffffff,
		cacheSize: 1}
}

// DirectEncodeBit encodes the least-significant bit of b with probability 1/2.
func (e *rangeEncoder) DirectEncodeBit(b uint32) error {
	// e.bitCounter++
	e.nrange >>= 1
	e.low += uint64(e.nrange) & (0 - (uint64(b) & 1))
	if err := e.normalize(); err != nil {
		return err
	}

	return nil
}

// EncodeBit encodes the least significant bit of b. The p value will be
// updated by the function depending on the bit encoded.
func (e *rangeEncoder) EncodeBit(b uint32, p *prob) error {
	// e.bitCounter++
	bound := p.bound(e.nrange)
	if b&1 == 0 {
		e.nrange = bound
		p.inc()
	} else {
		e.low += uint64(bound)
		e.nrange -= bound
		p.dec()
	}
	if err := e.normalize(); err != nil {
		return err
	}

	return nil
}

// Len returns the number of bytes written to the underlying writer.
func (e *rangeEncoder) Len() int64 {
	return e.w.Len()
}

// CloseLen returns the number of bytes Close would write now. The
// number might change after more data is encoded.
func (e *rangeEncoder) CloseLen() int64 {
	return e.cacheSize + 4
}

// Close writes a complete copy of the low value.
func (e *rangeEncoder) Close() error {
	for i := 0; i < 5; i++ {
		if err := e.shiftLow(); err != nil {
			return err
		}
	}
	return nil
}

// newRangeDecoder initializes a range decoder. It reads five bytes from the
// reader and therefore may return an error.
func newRangeDecoder(r io.Reader) (d *rangeDecoder, err error) {
	d = &rangeDecoder{r: newByteReader(r)}
	err = d.init()
	return
}

// possiblyAtEnd checks whether the decoder may be at the end of the stream.
func (d *rangeDecoder) possiblyAtEnd() bool {
	return d.code == 0
}

// DirectDecodeBit decodes a bit with probability 1/2. The return value b will
// contain the bit at the least-significant position. All other bits will be
// zero.
func (d *rangeDecoder) DirectDecodeBit() (b uint32, err error) {
	// d.bitCounter++
	d.nrange >>= 1
	d.code -= d.nrange
	t := 0 - (d.code >> 31)
	d.code += d.nrange & t

	// d.code will stay less then d.nrange

	if err = d.normalize(); err != nil {
		return 0, err
	}

	b = (t + 1) & 1

	return b, nil
}

// decodeBit decodes a single bit. The bit will be returned at the
// least-significant position. All other bits will be zero. The probability
// value will be updated.
func (d *rangeDecoder) DecodeBit(p *prob) (b uint32, err error) {
	// d.bitCounter++
	bound := p.bound(d.nrange)
	if d.code < bound {
		d.nrange = bound
		p.inc()
		b = 0
	} else {
		d.code -= bound
		d.nrange -= bound
		p.dec()
		b = 1
	}

	// d.code will stay less then d.nrange

	if err = d.normalize(); err != nil {
		return 0, err
	}

	return b, nil
}

// shiftLow shifts the low value for 8 bit. The shifted byte is written into
// the byte writer. The cache value is used to handle overflows.
func (e *rangeEncoder) shiftLow() error {
	if uint32(e.low) < 0xff000000 || (e.low>>32) != 0 {
		tmp := e.cache
		for {
			err := e.w.WriteByte(tmp + byte(e.low>>32))
			if err != nil {
				return err
			}
			tmp = 0xff
			e.cacheSize--
			if e.cacheSize <= 0 {
				if e.cacheSize < 0 {
					return negError{"cacheSize", e.cacheSize}
				}
				break
			}
		}
		e.cache = byte(uint32(e.low) >> 24)
	}
	e.cacheSize++
	e.low = uint64(uint32(e.low) << 8)
	return nil
}

// normalize handles shifts of nrange and low.
func (e *rangeEncoder) normalize() error {
	const top = 1 << 24
	if e.nrange >= top {
		return nil
	}
	e.nrange <<= 8
	return e.shiftLow()
}

// rangeDecoder decodes single bits of the range encoding stream.
type rangeDecoder struct {
	r      io.ByteReader
	nrange uint32
	code   uint32
}

// init initializes the range decoder, by reading from the byte reader.
func (d *rangeDecoder) init() error {
	d.nrange = 0xffffffff
	d.code = 0

	b, err := d.r.ReadByte()
	if err != nil {
		return err
	}
	if b != 0 {
		return lzmaError{"first byte not zero"}
	}

	for i := 0; i < 4; i++ {
		if err = d.updateCode(); err != nil {
			return err
		}
	}

	if d.code >= d.nrange {
		return lzmaError{"newRangeDecoder: d.code >= d.nrange"}
	}

	return nil
}

// updateCode reads a new byte into the code.
func (d *rangeDecoder) updateCode() error {
	b, err := d.r.ReadByte()
	if err != nil {
		return err
	}
	d.code = (d.code << 8) | uint32(b)
	return nil
}

// normalize the top value and update the code value.
func (d *rangeDecoder) normalize() error {
	// assume d.code < d.nrange
	const top = 1 << 24
	if d.nrange < top {
		d.nrange <<= 8
		// d.code < d.nrange will be maintained
		if err := d.updateCode(); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 Go Fightclub Authors
// This source code is released under the terms of the
// MIT license. Please see the file LICENSE for license details.

package main

import (
	"afp"
	"afp/filters/null"
	"afp/filters/fexec"
//	"./filters/delay"
//	"./filters/fexec"
//	"./filters/ospipe"
//	"./filters/demo"
)

var filters map[string]func() afp.Filter = map[string]func() afp.Filter {
	"exec"   : fexec.NewFilter,
	"nullsource" : null.NewNullSource,
	"nulllink"   : null.NewNullLink,
	"nullsink" : null.NewNullSink,
//	"delay"  : delay.NewFilter,
//	"stdin"  : ospipe.StdinSource,
//	"stdout" : ospipe.StdoutSink,
//	"nop"    : demo.NopFilter,
}<commit_msg>adding in stdoutsink<commit_after>// Copyright (c) 2010 Go Fightclub Authors
// This source code is released under the terms of the
// MIT license. Please see the file LICENSE for license details.

package main

import (
	"afp"
	"afp/filters/null"
	"afp/filters/fexec"
	"afp/filters/stdout"
//	"./filters/delay"
//	"./filters/fexec"
//	"./filters/ospipe"
//	"./filters/demo"
)

var filters map[string]func() afp.Filter = map[string]func() afp.Filter {
	"exec"   : fexec.NewFilter,
	"nullsource" : null.NewNullSource,
	"nulllink"   : null.NewNullLink,
	"nullsink" : null.NewNullSink,
	"stdoutsink" : stdout.NewStdoutSink,
//	"delay"  : delay.NewFilter,
//	"stdin"  : ospipe.StdinSource,
//	"stdout" : ospipe.StdoutSink,
//	"nop"    : demo.NopFilter,
}<|endoftext|>


<commit_before>// Copyright 2015 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ebiten

import (
	"image"
	"math"

	"github.com/hajimehoshi/ebiten/internal/endian"
	"github.com/hajimehoshi/ebiten/internal/graphics"
)

// An ImagePart is deprecated (as of 1.1.0-alpha): Use ImageParts instead.
type ImagePart struct {
	Dst image.Rectangle
	Src image.Rectangle
}

// An ImageParts represents the parts of the destination image and the parts of the source image.
type ImageParts interface {
	Len() int
	Dst(i int) (x0, y0, x1, y1 int)
	Src(i int) (x0, y0, x1, y1 int)
}

// NOTE: Remove this in the future.
type imageParts []ImagePart

func (p imageParts) Len() int {
	return len(p)
}

func (p imageParts) Dst(i int) (x0, y0, x1, y1 int) {
	dst := &p[i].Dst
	return dst.Min.X, dst.Min.Y, dst.Max.X, dst.Max.Y
}

func (p imageParts) Src(i int) (x0, y0, x1, y1 int) {
	src := &p[i].Src
	return src.Min.X, src.Min.Y, src.Max.X, src.Max.Y
}

type wholeImage struct {
	width  int
	height int
}

func (w *wholeImage) Len() int {
	return 1
}

func (w *wholeImage) Dst(i int) (x0, y0, x1, y1 int) {
	return 0, 0, w.width, w.height
}

func (w *wholeImage) Src(i int) (x0, y0, x1, y1 int) {
	return 0, 0, w.width, w.height
}

func u(x, width2p int) int16 {
	return int16(math.MaxInt16 * x / width2p)
}

func v(y, height2p int) int16 {
	return int16(math.MaxInt16 * y / height2p)
}

type textureQuads struct {
	parts  ImageParts
	width  int
	height int
}

func (t *textureQuads) vertices() []uint8 {
	size := graphics.QuadVertexSizeInBytes()
	l := t.parts.Len()
	vertices := make([]uint8, l*size)
	p := t.parts
	w, h := t.width, t.height
	width2p := graphics.NextPowerOf2Int(w)
	height2p := graphics.NextPowerOf2Int(h)
	n := 0
	for i := 0; i < l; i++ {
		dx0, dy0, dx1, dy1 := p.Dst(i)
		if dx0 == dx1 || dy0 == dy1 {
			continue
		}
		x0, y0, x1, y1 := int16(dx0), int16(dy0), int16(dx1), int16(dy1)
		sx0, sy0, sx1, sy1 := p.Src(i)
		if sx0 == sx1 || sy0 == sy1 {
			continue
		}
		u0, v0, u1, v1 := u(sx0, width2p), v(sy0, height2p), u(sx1, width2p), v(sy1, height2p)
		// Use direct assign here. `append` function might be slow on browsers.
		if endian.IsLittle() {
			vertices[size*n] = uint8(x0)
			vertices[size*n+1] = uint8(x0 >> 8)
			vertices[size*n+2] = uint8(y0)
			vertices[size*n+3] = uint8(y0 >> 8)
			vertices[size*n+4] = uint8(u0)
			vertices[size*n+5] = uint8(u0 >> 8)
			vertices[size*n+6] = uint8(v0)
			vertices[size*n+7] = uint8(v0 >> 8)
			vertices[size*n+8] = uint8(x1)
			vertices[size*n+9] = uint8(x1 >> 8)
			vertices[size*n+10] = uint8(y0)
			vertices[size*n+11] = uint8(y0 >> 8)
			vertices[size*n+12] = uint8(u1)
			vertices[size*n+13] = uint8(u1 >> 8)
			vertices[size*n+14] = uint8(v0)
			vertices[size*n+15] = uint8(v0 >> 8)
			vertices[size*n+16] = uint8(x0)
			vertices[size*n+17] = uint8(x0 >> 8)
			vertices[size*n+18] = uint8(y1)
			vertices[size*n+19] = uint8(y1 >> 8)
			vertices[size*n+20] = uint8(u0)
			vertices[size*n+21] = uint8(u0 >> 8)
			vertices[size*n+22] = uint8(v1)
			vertices[size*n+23] = uint8(v1 >> 8)
			vertices[size*n+24] = uint8(x1)
			vertices[size*n+25] = uint8(x1 >> 8)
			vertices[size*n+26] = uint8(y1)
			vertices[size*n+27] = uint8(y1 >> 8)
			vertices[size*n+28] = uint8(u1)
			vertices[size*n+29] = uint8(u1 >> 8)
			vertices[size*n+30] = uint8(v1)
			vertices[size*n+31] = uint8(v1 >> 8)
		} else {
			vertices[size*n] = uint8(x0 >> 8)
			vertices[size*n+1] = uint8(x0)
			vertices[size*n+2] = uint8(y0 >> 8)
			vertices[size*n+3] = uint8(y0)
			vertices[size*n+4] = uint8(u0 >> 8)
			vertices[size*n+5] = uint8(u0)
			vertices[size*n+6] = uint8(v0 >> 8)
			vertices[size*n+7] = uint8(v0)
			vertices[size*n+8] = uint8(x1 >> 8)
			vertices[size*n+9] = uint8(x1)
			vertices[size*n+10] = uint8(y0 >> 8)
			vertices[size*n+11] = uint8(y0)
			vertices[size*n+12] = uint8(u1 >> 8)
			vertices[size*n+13] = uint8(u1)
			vertices[size*n+14] = uint8(v0 >> 8)
			vertices[size*n+15] = uint8(v0)
			vertices[size*n+16] = uint8(x0 >> 8)
			vertices[size*n+17] = uint8(x0)
			vertices[size*n+18] = uint8(y1 >> 8)
			vertices[size*n+19] = uint8(y1)
			vertices[size*n+20] = uint8(u0 >> 8)
			vertices[size*n+21] = uint8(u0)
			vertices[size*n+22] = uint8(v1 >> 8)
			vertices[size*n+23] = uint8(v1)
			vertices[size*n+24] = uint8(x1 >> 8)
			vertices[size*n+25] = uint8(x1)
			vertices[size*n+26] = uint8(y1 >> 8)
			vertices[size*n+27] = uint8(y1)
			vertices[size*n+28] = uint8(u1 >> 8)
			vertices[size*n+29] = uint8(u1)
			vertices[size*n+30] = uint8(v1 >> 8)
			vertices[size*n+31] = uint8(v1)
		}
		n++
	}
	return vertices[:n*size]
}
<commit_msg>graphics: Refactoring imageparts.go<commit_after>// Copyright 2015 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ebiten

import (
	"image"
	"math"

	"github.com/hajimehoshi/ebiten/internal/endian"
	"github.com/hajimehoshi/ebiten/internal/graphics"
)

// An ImagePart is deprecated (as of 1.1.0-alpha): Use ImageParts instead.
type ImagePart struct {
	Dst image.Rectangle
	Src image.Rectangle
}

// An ImageParts represents the parts of the destination image and the parts of the source image.
type ImageParts interface {
	Len() int
	Dst(i int) (x0, y0, x1, y1 int)
	Src(i int) (x0, y0, x1, y1 int)
}

// NOTE: Remove this in the future.
type imageParts []ImagePart

func (p imageParts) Len() int {
	return len(p)
}

func (p imageParts) Dst(i int) (x0, y0, x1, y1 int) {
	dst := &p[i].Dst
	return dst.Min.X, dst.Min.Y, dst.Max.X, dst.Max.Y
}

func (p imageParts) Src(i int) (x0, y0, x1, y1 int) {
	src := &p[i].Src
	return src.Min.X, src.Min.Y, src.Max.X, src.Max.Y
}

type wholeImage struct {
	width  int
	height int
}

func (w *wholeImage) Len() int {
	return 1
}

func (w *wholeImage) Dst(i int) (x0, y0, x1, y1 int) {
	return 0, 0, w.width, w.height
}

func (w *wholeImage) Src(i int) (x0, y0, x1, y1 int) {
	return 0, 0, w.width, w.height
}

func u(x, width2p int) int16 {
	return int16(math.MaxInt16 * x / width2p)
}

func v(y, height2p int) int16 {
	return int16(math.MaxInt16 * y / height2p)
}

type textureQuads struct {
	parts  ImageParts
	width  int
	height int
}

func (t *textureQuads) vertices() []uint8 {
	size := graphics.QuadVertexSizeInBytes()
	l := t.parts.Len()
	vertices := make([]uint8, l*size)
	p := t.parts
	w, h := t.width, t.height
	width2p := graphics.NextPowerOf2Int(w)
	height2p := graphics.NextPowerOf2Int(h)
	n := 0
	vs := make([]int16, 16)
	for i := 0; i < l; i++ {
		dx0, dy0, dx1, dy1 := p.Dst(i)
		if dx0 == dx1 || dy0 == dy1 {
			continue
		}
		x0, y0, x1, y1 := int16(dx0), int16(dy0), int16(dx1), int16(dy1)
		sx0, sy0, sx1, sy1 := p.Src(i)
		if sx0 == sx1 || sy0 == sy1 {
			continue
		}
		u0, v0, u1, v1 := u(sx0, width2p), v(sy0, height2p), u(sx1, width2p), v(sy1, height2p)
		vs[0] = x0
		vs[1] = y0
		vs[2] = u0
		vs[3] = v0
		vs[4] = x1
		vs[5] = y0
		vs[6] = u1
		vs[7] = v0
		vs[8] = x0
		vs[9] = y1
		vs[10] = u0
		vs[11] = v1
		vs[12] = x1
		vs[13] = y1
		vs[14] = u1
		vs[15] = v1
		// Use direct assign here. `append` function might be slow on browsers.
		if endian.IsLittle() {
			for i, v := range vs {
				vertices[size*n+2*i] = uint8(v)
				vertices[size*n+2*i+1] = uint8(v >> 8)
			}
		} else {
			for i, v := range vs {
				vertices[size*n+2*i] = uint8(v >> 8)
				vertices[size*n+2*i+1] = uint8(v)
			}
		}
		n++
	}
	return vertices[:n*size]
}
<|endoftext|>


<commit_before>package gummyimage

import (
	"bytes"
	"errors"
	"fmt"
	"image"
	"image/color"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io"
	"io/ioutil"
	"math"
	"math/rand"
	"os"
	"strconv"
	"time"

	"code.google.com/p/freetype-go/freetype"
	"code.google.com/p/freetype-go/freetype/truetype"
)

type Gummy struct {
	Img   *image.RGBA
	Color *color.Color
	Font  *truetype.Font
}

// Color in HEX format: FAFAFA
// If hexColor = "" then random color
func NewDefaultGummy(w, h int, hexColor string) (*Gummy, error) {
	var bgColor color.Color
	if hexColor == "" {
		bgColor = randColor(255)

	} else {
		cr, _ := strconv.ParseUint(string(hexColor[:2]), 16, 64)
		cg, _ := strconv.ParseUint(string(hexColor[2:4]), 16, 64)
		cb, _ := strconv.ParseUint(string(hexColor[4:]), 16, 64)
		bgColor = color.RGBA{R: uint8(cr), G: uint8(cg), B: uint8(cb), A: 255}
	}

	return NewGummy(0, 0, w, h, bgColor)
}

func NewGummy(x, y, w, h int, gummyColor color.Color) (*Gummy, error) {

	img, err := createImg(x, y, w, h, gummyColor)

	if err != nil {
		return nil, err
	}

	return &Gummy{
		Img:   img,
		Color: &gummyColor,
		Font:  nil,
	}, nil
}

/*
Gets the image in the specified format (JPEG, GIF or PNG) in the specified writer
*/
func (g *Gummy) Get(format string, r io.Writer) error {

	switch format {
	case "jpeg", "JPEG", "jpg", "JPG":
		jpeg.Encode(r, g.Img, nil)
	case "png", "PNG":
		png.Encode(r, g.Img)
	case "gif", "GIF":
		gif.Encode(r, g.Img, nil)
	default:
		return errors.New("Wrong format")
	}

	return nil
}

func (g *Gummy) SaveJpeg(path string) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()

	return g.Get("jpeg", file)
}

func (g *Gummy) SaveGif(path string) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()

	return g.Get("gif", file)
}

func (g *Gummy) SavePng(path string) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()

	return g.Get("png", file)
}

func (g *Gummy) GetJpeg() ([]byte, error) {
	b := new(bytes.Buffer)
	err := g.Get("jpeg", b)
	return b.Bytes(), err
}

func (g *Gummy) GetGif() ([]byte, error) {
	b := new(bytes.Buffer)
	err := g.Get("gif", b)
	return b.Bytes(), err
}

func (g *Gummy) GetPng() ([]byte, error) {
	b := new(bytes.Buffer)
	err := g.Get("png", b)
	return b.Bytes(), err
}

// Color in HEX format: FAFAFA
func (g *Gummy) DrawText(text, textColor string, fontSize, xPosition, yPosition int) error {

	fc := freetype.NewContext()
	fc.SetDst(g.Img)
	fc.SetFont(g.Font)
	fc.SetClip(g.Img.Bounds())

	// Color parsing
	cr, _ := strconv.ParseUint(string(textColor[:2]), 16, 64)
	cg, _ := strconv.ParseUint(string(textColor[2:4]), 16, 64)
	cb, _ := strconv.ParseUint(string(textColor[4:]), 16, 64)
	c := image.NewUniform(color.RGBA{R: uint8(cr), G: uint8(cg), B: uint8(cb), A: 255})

	fc.SetSrc(c)
	fc.SetFontSize(float64(fontSize))

	_, err := fc.DrawString(text, freetype.Pt(xPosition, yPosition))

	return err
}

// Color in HEX format: FAFAFA
// If "" the color of the text is black or white depending on the brightness of the bg
func (g *Gummy) DrawTextSize(textColor string) error {

	// Get black or white depending on the background
	if textColor == "" {
		c := (*g.Color).(color.RGBA)
		if blackWithBackground(float64(c.R), float64(c.G), float64(c.B)) {
			textColor = "000000"
		} else {
			textColor = "FFFFFF"
		}
	}

	text := fmt.Sprintf("%dx%d", g.Img.Rect.Max.X, g.Img.Rect.Max.Y)

	// I can't get the text final size so more or less center the text with this
	// manual awful stuff :/
	size := g.Img.Rect.Max.Y

	if g.Img.Rect.Max.X < g.Img.Rect.Max.Y {
		size = g.Img.Rect.Max.X
	}

	textSize := (size - (size / 10 * 2))
	fontSize := textSize / len(text) * 2

	x := g.Img.Rect.Max.X/2 - textSize/2 - fontSize/8
	y := g.Img.Rect.Max.Y/2 + textSize/10 + fontSize/16

	return g.DrawText(
		text,
		textColor,
		fontSize,
		x,
		y,
	)
}

func LoadFont(path string) (*truetype.Font, error) {
	bs, err := ioutil.ReadFile(path)

	// quick debug
	if err != nil {
		fmt.Println(err)
	}
	f, err := truetype.Parse(bs)
	return f, err
}

func (g *Gummy) SetFont(path string) error {
	f, err := LoadFont(path)
	g.Font = f
	return err
}

func createImg(x, y, w, h int, gummyColor color.Color) (*image.RGBA, error) {
	img := image.NewRGBA(image.Rect(x, y, w, h))

	// Colorize!
	for y := img.Rect.Min.Y; y < img.Rect.Max.Y; y++ {
		for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ {
			img.Set(x, y, gummyColor)
		}
	}

	return img, nil

}

func randColor(alpha int) color.Color {

	random := func(min, max int) int {
		rand.Seed(time.Now().UnixNano())
		return rand.Intn(max-min) + min
	}

	r := uint8(random(0, 255))
	g := uint8(random(0, 255))
	b := uint8(random(0, 255))

	return color.RGBA{r, g, b, uint8(alpha)}

}

func inverseColor(r, g, b int) (rr, rg, rb int) {
	rr = 255 - r
	rg = 255 - g
	rb = 255 - b

	return
}

// Returns false if white text with that background
// Rrturns true if black text with that background
// Calculates based on the brightness
// Source: http://stackoverflow.com/a/2241471
func blackWithBackground(r, g, b float64) bool {

	perceivedBrightness := func(r, g, b float64) int {
		return int(math.Sqrt(r*r*0.241 + g*g*0.691 + b*b*0.068))
	}

	return perceivedBrightness(r, g, b) > 130
}
<commit_msg>Add custom centered text in image utils<commit_after>package gummyimage

import (
	"bytes"
	"errors"
	"fmt"
	"image"
	"image/color"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io"
	"io/ioutil"
	"math"
	"math/rand"
	"os"
	"strconv"
	"time"

	"code.google.com/p/freetype-go/freetype"
	"code.google.com/p/freetype-go/freetype/truetype"
)

type Gummy struct {
	Img   *image.RGBA
	Color *color.Color
	Font  *truetype.Font
}

// Color in HEX format: FAFAFA
// If hexColor = "" then random color
func NewDefaultGummy(w, h int, hexColor string) (*Gummy, error) {
	var bgColor color.Color
	if hexColor == "" {
		bgColor = randColor(255)

	} else {
		cr, _ := strconv.ParseUint(string(hexColor[:2]), 16, 64)
		cg, _ := strconv.ParseUint(string(hexColor[2:4]), 16, 64)
		cb, _ := strconv.ParseUint(string(hexColor[4:]), 16, 64)
		bgColor = color.RGBA{R: uint8(cr), G: uint8(cg), B: uint8(cb), A: 255}
	}

	return NewGummy(0, 0, w, h, bgColor)
}

func NewGummy(x, y, w, h int, gummyColor color.Color) (*Gummy, error) {

	img, err := createImg(x, y, w, h, gummyColor)

	if err != nil {
		return nil, err
	}

	return &Gummy{
		Img:   img,
		Color: &gummyColor,
		Font:  nil,
	}, nil
}

/*
Gets the image in the specified format (JPEG, GIF or PNG) in the specified writer
*/
func (g *Gummy) Get(format string, r io.Writer) error {

	switch format {
	case "jpeg", "JPEG", "jpg", "JPG":
		jpeg.Encode(r, g.Img, nil)
	case "png", "PNG":
		png.Encode(r, g.Img)
	case "gif", "GIF":
		gif.Encode(r, g.Img, nil)
	default:
		return errors.New("Wrong format")
	}

	return nil
}

func (g *Gummy) SaveJpeg(path string) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()

	return g.Get("jpeg", file)
}

func (g *Gummy) SaveGif(path string) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()

	return g.Get("gif", file)
}

func (g *Gummy) SavePng(path string) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()

	return g.Get("png", file)
}

func (g *Gummy) GetJpeg() ([]byte, error) {
	b := new(bytes.Buffer)
	err := g.Get("jpeg", b)
	return b.Bytes(), err
}

func (g *Gummy) GetGif() ([]byte, error) {
	b := new(bytes.Buffer)
	err := g.Get("gif", b)
	return b.Bytes(), err
}

func (g *Gummy) GetPng() ([]byte, error) {
	b := new(bytes.Buffer)
	err := g.Get("png", b)
	return b.Bytes(), err
}

// Color in HEX format: FAFAFA
func (g *Gummy) DrawText(text, textColor string, fontSize, xPosition, yPosition int) error {

	// Get black or white depending on the background
	if textColor == "" {
		c := (*g.Color).(color.RGBA)
		if blackWithBackground(float64(c.R), float64(c.G), float64(c.B)) {
			textColor = "000000"
		} else {
			textColor = "FFFFFF"
		}
	}

	fc := freetype.NewContext()
	fc.SetDst(g.Img)
	fc.SetFont(g.Font)
	fc.SetClip(g.Img.Bounds())

	// Color parsing
	cr, _ := strconv.ParseUint(string(textColor[:2]), 16, 64)
	cg, _ := strconv.ParseUint(string(textColor[2:4]), 16, 64)
	cb, _ := strconv.ParseUint(string(textColor[4:]), 16, 64)
	c := image.NewUniform(color.RGBA{R: uint8(cr), G: uint8(cg), B: uint8(cb), A: 255})

	fc.SetSrc(c)
	fc.SetFontSize(float64(fontSize))

	_, err := fc.DrawString(text, freetype.Pt(xPosition, yPosition))

	return err
}

func (g *Gummy) DrawTextCenter(text string, textColor string) error {
	// I can't get the text final size so more or less center the text with this
	// manual awful stuff :/
	size := g.Img.Rect.Max.Y

	if g.Img.Rect.Max.X < g.Img.Rect.Max.Y {
		size = g.Img.Rect.Max.X
	}

	textSize := (size - (size / 10 * 2))
	fontSize := textSize / len(text) * 2

	x := g.Img.Rect.Max.X/2 - textSize/2 - fontSize/8
	y := g.Img.Rect.Max.Y/2 + textSize/10 + fontSize/16

	return g.DrawText(
		text,
		textColor,
		fontSize,
		x,
		y,
	)
}

// Color in HEX format: FAFAFA
// If "" the color of the text is black or white depending on the brightness of the bg
func (g *Gummy) DrawTextSize(textColor string) error {
	return g.DrawTextCenter(fmt.Sprintf("%dx%d", g.Img.Rect.Max.X, g.Img.Rect.Max.Y), textColor)
}

func LoadFont(path string) (*truetype.Font, error) {
	bs, err := ioutil.ReadFile(path)

	// quick debug
	if err != nil {
		fmt.Println(err)
	}
	f, err := truetype.Parse(bs)
	return f, err
}

func (g *Gummy) SetFont(path string) error {
	f, err := LoadFont(path)
	g.Font = f
	return err
}

func createImg(x, y, w, h int, gummyColor color.Color) (*image.RGBA, error) {
	img := image.NewRGBA(image.Rect(x, y, w, h))

	// Colorize!
	for y := img.Rect.Min.Y; y < img.Rect.Max.Y; y++ {
		for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ {
			img.Set(x, y, gummyColor)
		}
	}

	return img, nil

}

func randColor(alpha int) color.Color {

	random := func(min, max int) int {
		rand.Seed(time.Now().UnixNano())
		return rand.Intn(max-min) + min
	}

	r := uint8(random(0, 255))
	g := uint8(random(0, 255))
	b := uint8(random(0, 255))

	return color.RGBA{r, g, b, uint8(alpha)}

}

func inverseColor(r, g, b int) (rr, rg, rb int) {
	rr = 255 - r
	rg = 255 - g
	rb = 255 - b

	return
}

// Returns false if white text with that background
// Rrturns true if black text with that background
// Calculates based on the brightness
// Source: http://stackoverflow.com/a/2241471
func blackWithBackground(r, g, b float64) bool {

	perceivedBrightness := func(r, g, b float64) int {
		return int(math.Sqrt(r*r*0.241 + g*g*0.691 + b*b*0.068))
	}

	return perceivedBrightness(r, g, b) > 130
}
<|endoftext|>


<commit_before>package webservice

import (
	ae "appengine"
	ds "appengine/datastore"
	"cache"
	"data"
	"encoding/json"
	"errors"
	"googlebooks"
	"isbn13"
	"net/http"
	"persistence"
)

func init() {
	http.HandleFunc("/volumes/", serveLookup)
	http.HandleFunc("/volumes", serveImportExport)
}

func LookupISBN(ctx ae.Context, country string, isbn isbn13.ISBN13) (resp *data.BookMetaData, err error) {
	funcs := []func(ae.Context, string, isbn13.ISBN13) (*data.BookMetaData, error){
		func(ctx ae.Context, country string, isbn isbn13.ISBN13) (*data.BookMetaData, error) {
			shelf, err := persistence.LookupBookshelf(ctx)
			if err == nil {
				return shelf.LookupInfo(isbn)
			}

			return nil, err
		},
		cache.LookupISBN,
		persistence.LookupISBN,
		func(ctx ae.Context, country string, isbn isbn13.ISBN13) (*data.BookMetaData, error) {
			r, err := googlebooks.LookupISBN(ctx, country, isbn)

			if err == nil {
				go cache.CacheISBNResult(ctx, country, isbn, r)
				go persistence.StoreISBNResult(ctx, country, isbn, r)
			}

			return r, err
		},
	}

	var multi ae.MultiError

	for i, f := range funcs {
		if result, err := f(ctx, country, isbn); err == nil && result != nil {
			ctx.Debugf("Found info %v after %d iterations\n", result, i)
			return result, nil
		} else if err != nil {
			multi = append(multi, err)
		}
	}

	return nil, multi
}

func serveImportExport(w http.ResponseWriter, rq *http.Request) {
	ctx := ae.NewContext(rq)
	var err error
	var shelf *data.Bookshelf
	status := http.StatusBadRequest

	switch rq.Method {
	case "GET":
		shelf, err = persistence.LookupBookshelf(ctx)
	case "PUT":
		decode := json.NewDecoder(rq.Body)
		shelf = new(data.Bookshelf)
		if err = decode.Decode(shelf); err == nil {
			status = http.StatusInternalServerError
			err = persistence.StoreBookshelf(ctx, shelf)
		}
	}

	if err != nil {
		reportError(err)
		w.WriteHeader(status)
	} else {
		encode := json.NewEncoder(w)
		w.WriteHeader(http.StatusOK)
		w.Header().Add("Content-Type", "application/json")
		if err = encode.Encode(shelf); err != nil {
			ctx.Errorf("Could not report error on encode: %s\n", err.Error())
		}

	}
}

func serveLookup(w http.ResponseWriter, rq *http.Request) {
	isbn, err := isbn13.New(rq.URL.Path[9:])
	status := http.StatusBadRequest

	if err == nil {
		status = http.StatusInternalServerError
		switch rq.Method {
		case "GET":
			err = handleGet(w, rq, isbn)
		case "PUT":
			err = handlePut(w, rq, isbn)
		default:
			status = http.StatusMethodNotAllowed
			err = errors.New("Unsupported operation. Only GET, PUT and DELETE methods are allowed")
		}

	}

	if err != nil {
		reportError(err)
		w.WriteHeader(status)
	}
}

func reportError(e error) {
	if me, ok := e.(ae.MultiError); ok {
		for _, next := range me {
			reportError(next)
		}
	} else {
		ctx.Errorf("Error reported: %s", e.Error())
	}
}

func handlePut(w http.ResponseWriter, rq *http.Request, isbn isbn13.ISBN13) error {
	ctx := ae.NewContext(rq)
	shelf, err := persistence.LookupBookshelf(ctx)

	if err == ds.ErrNoSuchEntity {
		err = nil
		shelf = new(data.Bookshelf)
	}

	if err == nil {
		decode := json.NewDecoder(rq.Body)
		info := new(data.BookMetaData)
		if err = decode.Decode(info); err == nil {
			if ptr, _ := shelf.LookupInfo(isbn); ptr != nil {
				*ptr = *info
			} else {
				shelf.Books = append(shelf.Books, *info)
			}

			err = persistence.StoreBookshelf(ctx, shelf)
		}
	}
	return err

}

func handleGet(w http.ResponseWriter, rq *http.Request, isbn isbn13.ISBN13) error {
	var reply *data.BookMetaData
	var err error
	ctx := ae.NewContext(rq)
	country := determineCountry(rq)
	if reply, err = LookupISBN(ctx, country, isbn); err == nil {
		encode := json.NewEncoder(w)
		w.WriteHeader(http.StatusOK)
		w.Header().Add("Content-Type", "application/json")
		if err = encode.Encode(reply); err == nil {
			return nil
		}
	}

	return err
}

func determineCountry(rq *http.Request) string {
	header := rq.Header["X-AppEngine-Country"]
	if len(header) > 0 {
		return header[0]
	}
	query := rq.URL.Query()["country"]

	if len(query) > 0 {
		return query[0]
	}

	return "unknown"

}
<commit_msg>Rewrote WS with somewhat better abstraction<commit_after>package webservice

import (
	ae "appengine"
	ds "appengine/datastore"
	"cache"
	"data"
	"encoding/json"
	"errors"
	"googlebooks"
	"isbn13"
	"net/http"
	"persistence"
)

type Call struct {
	Context  ae.Context
	Request  *http.Request
	Response http.ResponseWriter
}

func (call *Call) ReportError(err error) {
	if me, ok := err.(ae.MultiError); ok {
		for _, next := range me {
			call.ReportError(next)
		}
	} else {
		call.Context.Errorf("Error reported: %s", err.Error())
	}
}

func (call *Call) DetermineCountry() string {
	header := call.Request.Header["X-AppEngine-Country"]
	if len(header) > 0 {
		return header[0]
	}

	query := call.Request.URL.Query()["country"]

	if len(query) > 0 {
		return query[0]
	}

	return "unknown"
}

type CallHandler func(*Call) error

func (function CallHandler) ServeHTTP(w http.ResponseWriter, rq *http.Request) {
	call := Call{
		Context:  ae.NewContext(rq),
		Request:  rq,
		Response: w,
	}

	err := function(&call)

	if err != nil {
		call.ReportError(err)
	}
}

func init() {
	http.Handle("/volumes/", CallHandler(serveVolumeSingle))
	http.Handle("/volumes", CallHandler(serveVolumeBulk))
}

func serveVolumeBulk(call *Call) (err error) {
	var shelf *data.Bookshelf
	status := http.StatusInternalServerError
	switch call.Request.Method {
	case "GET":
		shelf, err = persistence.LookupBookshelf(call.Context)
	case "PUT":
		shelf, err = putVolumeBulk(call)
	default:
		status = http.StatusMethodNotAllowed
		err = errors.New("Unsupported operation. Only GET, PUT and DELETE methods are allowed")
	}

	if err == nil {
		encode := json.NewEncoder(call.Response)
		call.Response.Header().Add("Content-Type", "application/json")
		call.Response.WriteHeader(http.StatusOK)
		err = encode.Encode(shelf)
	} else {
		call.Response.WriteHeader(status)
	}

	return err
}

func putVolumeBulk(call *Call) (shelf *data.Bookshelf, err error) {
	decode := json.NewDecoder(call.Request.Body)
	shelf = new(data.Bookshelf)
	if err = decode.Decode(shelf); err == nil {
		err = persistence.StoreBookshelf(call.Context, shelf)
	}

	return
}

func serveVolumeSingle(call *Call) error {
	status := http.StatusBadRequest
	isbn, err := isbn13.New(call.Request.URL.Path[9:])
	var book *data.BookMetaData

	if err == nil {
		status = http.StatusInternalServerError
		switch call.Request.Method {
		case "GET":
			book, err = compositeISBNLookup(call.Context, call.DetermineCountry(), isbn)
		case "PUT":
			book, err = putVolumeSingle(call, isbn)
		default:
			status = http.StatusMethodNotAllowed
			err = errors.New("Unsupported operation. Only GET, PUT and DELETE methods are allowed")
		}
	}

	if err == nil {
		encode := json.NewEncoder(call.Response)

		call.Response.Header().Add("Content-Type", "application/json")
		call.Response.WriteHeader(http.StatusOK)
		err = encode.Encode(book)
	} else {
		call.Response.WriteHeader(status)
	}

	return err
}

func putVolumeSingle(call *Call, isbn isbn13.ISBN13) (*data.BookMetaData, error) {
	shelf, err := persistence.LookupBookshelf(call.Context)
	var info *data.BookMetaData

	if err == ds.ErrNoSuchEntity {
		err = nil
		shelf = new(data.Bookshelf)
	}

	if err == nil {
		decode := json.NewDecoder(call.Request.Body)
		info = new(data.BookMetaData)
		if err = decode.Decode(info); err == nil {
			if ptr, _ := shelf.LookupInfo(isbn); ptr != nil {
				*ptr = *info
			} else {
				shelf.Books = append(shelf.Books, *info)
			}

			err = persistence.StoreBookshelf(call.Context, shelf)
		}
	}
	return info, err
}

func compositeISBNLookup(ctx ae.Context, country string, isbn isbn13.ISBN13) (resp *data.BookMetaData, err error) {
	funcs := []func(ae.Context, string, isbn13.ISBN13) (*data.BookMetaData, error){
		func(ctx ae.Context, country string, isbn isbn13.ISBN13) (*data.BookMetaData, error) {
			shelf, err := persistence.LookupBookshelf(ctx)
			if err == nil {
				return shelf.LookupInfo(isbn)
			}

			return nil, err
		},
		cache.LookupISBN,
		persistence.LookupISBN,
		func(ctx ae.Context, country string, isbn isbn13.ISBN13) (*data.BookMetaData, error) {
			r, err := googlebooks.LookupISBN(ctx, country, isbn)

			if err == nil {
				go cache.CacheISBNResult(ctx, country, isbn, r)
				go persistence.StoreISBNResult(ctx, country, isbn, r)
			}

			return r, err
		},
	}

	var multi ae.MultiError

	for i, f := range funcs {
		if result, err := f(ctx, country, isbn); err == nil && result != nil {
			ctx.Debugf("Found info %v after %d iterations\n", result, i)
			return result, nil
		} else if err != nil {
			multi = append(multi, err)
		}
	}

	return nil, multi
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package metrics

import (
	"sync"
	"time"

	compbasemetrics "k8s.io/component-base/metrics"
	"k8s.io/component-base/metrics/legacyregistry"
)

/*
 * By default, all the following metrics are defined as falling under
 * ALPHA stability level https://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/20190404-kubernetes-control-plane-metrics-stability.md#stability-classes)
 *
 * Promoting the stability level of the metric is a responsibility of the component owner, since it
 * involves explicitly acknowledging support for the metric across multiple releases, in accordance with
 * the metric stability policy.
 */
var (
	etcdRequestLatency = compbasemetrics.NewHistogramVec(
		&compbasemetrics.HistogramOpts{
			Name:           "etcd_request_duration_seconds",
			Help:           "Etcd request latency in seconds for each operation and object type.",
			StabilityLevel: compbasemetrics.ALPHA,
		},
		[]string{"operation", "type"},
	)
	objectCounts = compbasemetrics.NewGaugeVec(
		&compbasemetrics.GaugeOpts{
			Name:           "etcd_object_counts",
			Help:           "Number of stored objects at the time of last check split by kind.",
			StabilityLevel: compbasemetrics.ALPHA,
		},
		[]string{"resource"},
	)

	deprecatedEtcdRequestLatenciesSummary = compbasemetrics.NewSummaryVec(
		&compbasemetrics.SummaryOpts{
			Name:              "etcd_request_latencies_summary",
			Help:              "Etcd request latency summary in microseconds for each operation and object type.",
			StabilityLevel:    compbasemetrics.ALPHA,
			DeprecatedVersion: "1.14.0",
		},
		[]string{"operation", "type"},
	)
)

var registerMetrics sync.Once

// Register all metrics.
func Register() {
	// Register the metrics.
	registerMetrics.Do(func() {
		legacyregistry.MustRegister(etcdRequestLatency)
		legacyregistry.MustRegister(objectCounts)

		// TODO(danielqsj): Remove the following metrics, they are deprecated
		legacyregistry.MustRegister(deprecatedEtcdRequestLatenciesSummary)
	})
}

// UpdateObjectCount sets the etcd_object_counts metric.
func UpdateObjectCount(resourcePrefix string, count int64) {
	objectCounts.WithLabelValues(resourcePrefix).Set(float64(count))
}

// RecordEtcdRequestLatency sets the etcd_request_duration_seconds metrics.
func RecordEtcdRequestLatency(verb, resource string, startTime time.Time) {
	etcdRequestLatency.WithLabelValues(verb, resource).Observe(sinceInSeconds(startTime))
	deprecatedEtcdRequestLatenciesSummary.WithLabelValues(verb, resource).Observe(sinceInMicroseconds(startTime))
}

// Reset resets the etcd_request_duration_seconds metric.
func Reset() {
	etcdRequestLatency.Reset()

	deprecatedEtcdRequestLatenciesSummary.Reset()
}

// sinceInMicroseconds gets the time since the specified start in microseconds.
func sinceInMicroseconds(start time.Time) float64 {
	return float64(time.Since(start).Nanoseconds() / time.Microsecond.Nanoseconds())
}

// sinceInSeconds gets the time since the specified start in seconds.
func sinceInSeconds(start time.Time) float64 {
	return time.Since(start).Seconds()
}
<commit_msg>remove deprecated metrics of etcd<commit_after>/*
Copyright 2015 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package metrics

import (
	"sync"
	"time"

	compbasemetrics "k8s.io/component-base/metrics"
	"k8s.io/component-base/metrics/legacyregistry"
)

/*
 * By default, all the following metrics are defined as falling under
 * ALPHA stability level https://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/20190404-kubernetes-control-plane-metrics-stability.md#stability-classes)
 *
 * Promoting the stability level of the metric is a responsibility of the component owner, since it
 * involves explicitly acknowledging support for the metric across multiple releases, in accordance with
 * the metric stability policy.
 */
var (
	etcdRequestLatency = compbasemetrics.NewHistogramVec(
		&compbasemetrics.HistogramOpts{
			Name:           "etcd_request_duration_seconds",
			Help:           "Etcd request latency in seconds for each operation and object type.",
			StabilityLevel: compbasemetrics.ALPHA,
		},
		[]string{"operation", "type"},
	)
	objectCounts = compbasemetrics.NewGaugeVec(
		&compbasemetrics.GaugeOpts{
			Name:           "etcd_object_counts",
			Help:           "Number of stored objects at the time of last check split by kind.",
			StabilityLevel: compbasemetrics.ALPHA,
		},
		[]string{"resource"},
	)
)

var registerMetrics sync.Once

// Register all metrics.
func Register() {
	// Register the metrics.
	registerMetrics.Do(func() {
		legacyregistry.MustRegister(etcdRequestLatency)
		legacyregistry.MustRegister(objectCounts)
	})
}

// UpdateObjectCount sets the etcd_object_counts metric.
func UpdateObjectCount(resourcePrefix string, count int64) {
	objectCounts.WithLabelValues(resourcePrefix).Set(float64(count))
}

// RecordEtcdRequestLatency sets the etcd_request_duration_seconds metrics.
func RecordEtcdRequestLatency(verb, resource string, startTime time.Time) {
	etcdRequestLatency.WithLabelValues(verb, resource).Observe(sinceInSeconds(startTime))
}

// Reset resets the etcd_request_duration_seconds metric.
func Reset() {
	etcdRequestLatency.Reset()
}

// sinceInSeconds gets the time since the specified start in seconds.
func sinceInSeconds(start time.Time) float64 {
	return time.Since(start).Seconds()
}
<|endoftext|>


<commit_before>package genomego

import (
	"fmt"
	"math/rand"
	"time"
)

type Population struct {
	Rand func() float32
}

func NewPopulation() *Population {
	generator := rand.New(rand.NewSource(time.Now().UnixNano()))
	return &Population{Rand: func() float32 { return generator.Float32() }}
}

type Individual struct {
	size   int
	genome []bool
	p      *Population
}

func (p *Population) NewIndividual(size int) *Individual {
	ind := Individual{size: size, p: p}
	ind.genome = make([]bool, ind.size)
	for i := range ind.genome {
		ind.genome[i] = (p.Rand() < 0.5)
	}
	return &ind
}

// Clone creates a new Individual with the same genome.
func (me *Individual) Clone() *Individual {
	them := me.cloneEmpty()
	copy(them.genome, me.genome)
	return them
}

// cloneEmpty clones an Individual, but leaves the genome initialized
// to the zero values.
func (me *Individual) cloneEmpty() *Individual {
	them := &Individual{
		size:   me.size,
		p:      me.p,
		genome: make([]bool, me.size),
	}
	return them
}

func (me *Individual) Crossover(other *Individual, pos int) (child1, child2 *Individual) {
	if len(other.genome) != len(me.genome) {
		panic("Other individual has different length!")
	}

	child1 = me.cloneEmpty()
	child2 = me.cloneEmpty()
	for i := 0; i < pos; i++ {
		child1.genome[i] = me.genome[i]
		child2.genome[i] = other.genome[i]
	}

	for i := pos; i < me.size; i++ {
		child2.genome[i] = me.genome[i]
		child1.genome[i] = other.genome[i]
	}

	return
}

// String makes Individual implement interface Stringer (see fmt)
// so that when printed Println or printf %v, we only show useful stuff.
func (me *Individual) String() string {
	return fmt.Sprint(me.genome)
}

// Mutate flips the alelles in the Individual's genome with
// a probability of rate (for 0.0 <= rate < 1.0)
func (me *Individual) Mutate(rate float32) {
	for i := 0; i < me.size; i++ {
		if me.p.Rand() < rate {
			me.genome[i] = !me.genome[i]
		}
	}
}
<commit_msg>Renamed population to factory<commit_after>package genomego

import (
	"fmt"
	"math/rand"
	"time"
)

type IndividualFactory struct {
	Rand func() float32
}

func NewIndividualFactory() *IndividualFactory {
	generator := rand.New(rand.NewSource(time.Now().UnixNano()))
	return &IndividualFactory{Rand: func() float32 { return generator.Float32() }}
}

type Individual struct {
	size   int
	genome []bool
	p      *IndividualFactory
}

func (p *IndividualFactory) NewIndividual(size int) *Individual {
	ind := Individual{size: size, p: p}
	ind.genome = make([]bool, ind.size)
	for i := range ind.genome {
		ind.genome[i] = (p.Rand() < 0.5)
	}
	return &ind
}

// Clone creates a new Individual with the same genome.
func (me *Individual) Clone() *Individual {
	them := me.cloneEmpty()
	copy(them.genome, me.genome)
	return them
}

// cloneEmpty clones an Individual, but leaves the genome initialized
// to the zero values.
func (me *Individual) cloneEmpty() *Individual {
	them := &Individual{
		size:   me.size,
		p:      me.p,
		genome: make([]bool, me.size),
	}
	return them
}

func (me *Individual) Crossover(other *Individual, pos int) (child1, child2 *Individual) {
	if len(other.genome) != len(me.genome) {
		panic("Other individual has different length!")
	}

	child1 = me.cloneEmpty()
	child2 = me.cloneEmpty()
	for i := 0; i < pos; i++ {
		child1.genome[i] = me.genome[i]
		child2.genome[i] = other.genome[i]
	}

	for i := pos; i < me.size; i++ {
		child2.genome[i] = me.genome[i]
		child1.genome[i] = other.genome[i]
	}

	return
}

// String makes Individual implement interface Stringer (see fmt)
// so that when printed Println or printf %v, we only show useful stuff.
func (me *Individual) String() string {
	return fmt.Sprint(me.genome)
}

// Mutate flips the alelles in the Individual's genome with
// a probability of rate (for 0.0 <= rate < 1.0)
func (me *Individual) Mutate(rate float32) {
	for i := 0; i < me.size; i++ {
		if me.p.Rand() < rate {
			me.genome[i] = !me.genome[i]
		}
	}
}
<|endoftext|>


<commit_before>package main

import "github.com/fatih/color"

// conect to server operation
func connect(matched []Server, printOnly bool) {
	if len(matched) == 0 {
		color.Cyan("No server match patterns")
	} else if len(matched) == 1 {
		color.Green("%s", matched[0].getConnectionString())
		if !printOnly {
			matched[0].connect()
		}
	} else {
		color.Cyan("Multiple servers match patterns:")
		for _, s := range matched {
			color.White(s.getConnectionString())
		}
	}
}

// upload file to server operation
func upload(src string, dest string, matched []Server, printOnly bool) {
	if len(matched) == 0 {
		color.Cyan("No server match patterns")
	} else if len(matched) == 1 {
		color.Green("%s", matched[0].getUploadString(src, dest))
		if !printOnly {
			matched[0].upload(src, dest)
		}
	} else {
		color.Cyan("Multiple servers match patterns:")
		for _, s := range matched {
			color.White(s.getUploadString(src, dest))
		}
	}
}

// download file from server operation
func download(src string, dest string, matched []Server, printOnly bool) {
	if len(matched) == 0 {
		color.Cyan("No server match patterns")
	} else if len(matched) == 1 {
		color.Green("%s", matched[0].getDownloadString(src, dest))
		if !printOnly {
			matched[0].download(src, dest)
		}
	} else {
		color.Cyan("Multiple servers match patterns:")
		for _, s := range matched {
			color.White(s.getDownloadString(src, dest))
		}
	}
}
<commit_msg>updated operations output<commit_after>package main

import (
	"fmt"

	"github.com/fatih/color"
)

// conect to server operation
func connect(matched []Server, printOnly bool) {
	if len(matched) == 0 {
		color.Cyan("No server match patterns")
	} else if len(matched) == 1 {
		color.Green(fmt.Sprintf("%s: %s", matched[0].Name, matched[0].getConnectionString()))
		if !printOnly {
			matched[0].connect()
		}
	} else {
		color.Cyan("Multiple servers match patterns:")
		for _, s := range matched {
			color.White(fmt.Sprintf("%s: %s", s.Name, s.getConnectionString()))
		}
	}
}

// upload file to server operation
func upload(src string, dest string, matched []Server, printOnly bool) {
	if len(matched) == 0 {
		color.Cyan("No server match patterns")
	} else if len(matched) == 1 {
		color.Green(fmt.Sprintf("%s: %s", matched[0].Name, matched[0].getUploadString(src, dest)))
		if !printOnly {
			matched[0].upload(src, dest)
		}
	} else {
		color.Cyan("Multiple servers match patterns:")
		for _, s := range matched {
			color.White(fmt.Sprintf("%s: %s", s.Name, s.getUploadString(src, dest)))
		}
	}
}

// download file from server operation
func download(src string, dest string, matched []Server, printOnly bool) {
	if len(matched) == 0 {
		color.Cyan("No server match patterns")
	} else if len(matched) == 1 {
		color.Green(fmt.Sprintf("%s: %s", matched[0].Name, matched[0].getDownloadString(src, dest)))
		if !printOnly {
			matched[0].download(src, dest)
		}
	} else {
		color.Cyan("Multiple servers match patterns:")
		for _, s := range matched {
			color.White(fmt.Sprintf("%s: %s", s.Name, s.getDownloadString(src, dest)))
		}
	}
}
<|endoftext|>


<commit_before>package domain

// User is a type where the user attributes are stored
type User struct {
	ID          int
	Username    string
	AccessToken string
}

// Link defines the structure to the navigation links
type Link struct {
	Title string
	URL   string
}

type Repository struct {
	Name        *string `json:"name,omitempty"`
	FullName    *string `json:"full_name,omitempty"`
	Description *string `json:"description,omitempty"`
	Private     *bool   `json:"private,omitempty"`
	HTMLURL     *string `json:"html_url,omitempty"`
	CloneURL    *string `json:"clone_url,omitempty"`
	SSHURL      *string `json:"ssh_url,omitempty"`
}

type Key struct {
	ID    *int    `json:"id,omitempty"`
	Key   *string `json:"key,omitempty"`
	Title *string `json:"title,omitempty"`
	URL   *string `json:"url,omitempty"`
}

type File struct {
	Path    string `json:"path"`
	Content []byte `json:"content"`
}

type Author struct {
	Author  string `json:"author"`
	Message string `json:"message"`
	Branch  string `json:"branch,omitempty"`
	Email   string `json:"email"`
}
<commit_msg>Add Username field to user<commit_after>package domain

// User is a type where the user attributes are stored
type User struct {
	ID             int
	Username       string
	AccessToken    string
	ExpirationDate int64
}

// Link defines the structure to the navigation links
type Link struct {
	Title string
	URL   string
}

type Repository struct {
	Name        *string `json:"name,omitempty"`
	FullName    *string `json:"full_name,omitempty"`
	Description *string `json:"description,omitempty"`
	Private     *bool   `json:"private,omitempty"`
	HTMLURL     *string `json:"html_url,omitempty"`
	CloneURL    *string `json:"clone_url,omitempty"`
	SSHURL      *string `json:"ssh_url,omitempty"`
}

type Key struct {
	ID    *int    `json:"id,omitempty"`
	Key   *string `json:"key,omitempty"`
	Title *string `json:"title,omitempty"`
	URL   *string `json:"url,omitempty"`
}

type File struct {
	Path    string `json:"path"`
	Content []byte `json:"content"`
}

type Author struct {
	Author  string `json:"author"`
	Message string `json:"message"`
	Branch  string `json:"branch,omitempty"`
	Email   string `json:"email"`
}
<|endoftext|>


<commit_before>package matching

import (
	"encoding/json"
	"reflect"

	"github.com/SpectoLabs/hoverfly/core/util"
)

func JsonMatch(matchingString string, toMatch string) bool {
	minifiedMatchingString, err := util.MinifyJson(matchingString)
	if err != nil {
		return false
	}

	minifiedToMatch, err := util.MinifyJson(toMatch)
	if err != nil {
		return false
	}

	var matchingJson, toMatchJson map[string]interface{}

	err = json.Unmarshal([]byte(minifiedMatchingString), &matchingJson)
	if err != nil {
		return false
	}

	err = json.Unmarshal([]byte(minifiedToMatch), &toMatchJson)
	if err != nil {
		return false
	}

	return reflect.DeepEqual(matchingJson, toMatchJson)
}
<commit_msg>Simplified JsonMatch<commit_after>package matching

import (
	"reflect"

	"github.com/SpectoLabs/hoverfly/core/util"
)

func JsonMatch(matchingString string, toMatch string) bool {
	minifiedMatchingString, err := util.MinifyJson(matchingString)
	if err != nil {
		return false
	}

	minifiedToMatch, err := util.MinifyJson(toMatch)
	if err != nil {
		return false
	}

	return reflect.DeepEqual(minifiedMatchingString, minifiedToMatch)
}
<|endoftext|>


<commit_before>package mapping

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"

	"github.com/Shop2market/go-client/mapping/cache"
)

const PATH = "/api/v1/mapping_files.json"

type Repo struct {
	endpoint string
	username string
	password string

	Cache *cache.Cache
}

func New(endpoint, username, password string) (repo *Repo, err error) {
	if !strings.HasSuffix(endpoint, PATH) {
		err = fmt.Errorf("wrong endpoint: `%s`", endpoint)
		return
	}
	repo = &Repo{endpoint, username, password, cache.New()}
	return
}

func (repo *Repo) FindAllMappings() (mappings map[string][][]string, err error) {
	// if repo.Cache.IsValid() {
	// 	mappings, err = repo.Cache.Get()
	// 	return
	// }

	request, err := http.NewRequest("GET", repo.endpoint, nil)
	request.SetBasicAuth(repo.username, repo.password)
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		return
	}
	defer response.Body.Close()
	if response.StatusCode >= 400 {
		err = fmt.Errorf("Responded with error: %s", response.Status)
		return
	}
	err = json.NewDecoder(response.Body).Decode(&mappings)
	if err != nil {
		return
	}
	//repo.Cache.Update(mappings)

	return
}

func (repo *Repo) Find(name string) (mapping [][]string, err error) {
	mappings, err := repo.FindAllMappings()
	if err != nil {
		return
	}
	mapping, ok := mappings[name]
	if ok {
		return
	}
	err = fmt.Errorf("can't find `%s` mapping", name)
	return
}

func PrepareRequest(repo *Repo) (request *http.Request, err error) {
	request, err = http.NewRequest("GET", repo.endpoint, nil)
	if err != nil {
		return
	}
	request.SetBasicAuth(repo.username, repo.password)
	return
}
<commit_msg>TTPD-174: enables cache back<commit_after>package mapping

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"

	"github.com/Shop2market/go-client/mapping/cache"
)

const PATH = "/api/v1/mapping_files.json"

type Repo struct {
	endpoint string
	username string
	password string

	Cache *cache.Cache
}

func New(endpoint, username, password string) (repo *Repo, err error) {
	if !strings.HasSuffix(endpoint, PATH) {
		err = fmt.Errorf("wrong endpoint: `%s`", endpoint)
		return
	}
	repo = &Repo{endpoint, username, password, cache.New()}
	return
}

func (repo *Repo) FindAllMappings() (mappings map[string][][]string, err error) {
	if repo.Cache.IsValid() {
		mappings, err = repo.Cache.Get()
		return
	}

	request, err := http.NewRequest("GET", repo.endpoint, nil)
	request.SetBasicAuth(repo.username, repo.password)
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		return
	}
	defer response.Body.Close()
	if response.StatusCode >= 400 {
		err = fmt.Errorf("Responded with error: %s", response.Status)
		return
	}
	err = json.NewDecoder(response.Body).Decode(&mappings)
	if err != nil {
		return
	}
	repo.Cache.Update(mappings)

	return
}

func (repo *Repo) Find(name string) (mapping [][]string, err error) {
	mappings, err := repo.FindAllMappings()
	if err != nil {
		return
	}
	mapping, ok := mappings[name]
	if ok {
		return
	}
	err = fmt.Errorf("can't find `%s` mapping", name)
	return
}

func PrepareRequest(repo *Repo) (request *http.Request, err error) {
	request, err = http.NewRequest("GET", repo.endpoint, nil)
	if err != nil {
		return
	}
	request.SetBasicAuth(repo.username, repo.password)
	return
}
<|endoftext|>


<commit_before><commit_msg>Few changes<commit_after><|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/Sirupsen/logrus/hooks/sentry"
	"github.com/codegangsta/cli"
	"github.com/rcrowley/go-metrics"
	"github.com/rcrowley/go-metrics/librato"
	"github.com/streadway/amqp"
	"github.com/travis-ci/worker"
	"github.com/travis-ci/worker/backend"
	"github.com/travis-ci/worker/config"
	"github.com/travis-ci/worker/context"
	gocontext "golang.org/x/net/context"
)

func main() {
	app := cli.NewApp()
	app.Usage = "Travis Worker daemon"
	app.Version = worker.VersionString
	app.Author = "Travis CI GmbH"
	app.Email = "contact+travis-worker@travis-ci.org"

	app.Flags = config.Flags
	app.Action = runWorker

	app.Run(os.Args)
}

func runWorker(c *cli.Context) {
	ctx, cancel := gocontext.WithCancel(gocontext.Background())
	logger := context.LoggerFromContext(ctx)

	logrus.SetFormatter(&logrus.TextFormatter{DisableColors: true})

	if c.String("pprof-port") != "" {
		// Start net/http/pprof server
		go func() {
			http.ListenAndServe(fmt.Sprintf("localhost:%s", c.String("pprof-port")), nil)
		}()
	}

	if c.Bool("debug") {
		logrus.SetLevel(logrus.DebugLevel)
	}

	cfg := config.ConfigFromCLIContext(c)

	if c.Bool("echo-config") {
		config.WriteEnvConfig(cfg, os.Stdout)
		return
	}

	logger.WithFields(logrus.Fields{
		"cfg": fmt.Sprintf("%#v", cfg),
	}).Debug("read config")

	logger.Info("worker started")
	defer logger.Info("worker finished")

	if cfg.SentryDSN != "" {
		sentryHook, err := logrus_sentry.NewSentryHook(cfg.SentryDSN, []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel})
		if err != nil {
			logger.WithField("err", err).Error("couldn't create sentry hook")
		}

		logrus.AddHook(sentryHook)
	}

	if cfg.LibratoEmail != "" && cfg.LibratoToken != "" && cfg.LibratoSource != "" {
		logger.Info("starting librato metrics reporter")
		go librato.Librato(metrics.DefaultRegistry, time.Minute, cfg.LibratoEmail, cfg.LibratoToken, cfg.LibratoSource, []float64{0.95}, time.Millisecond)
	} else if !c.Bool("silence-metrics") {
		logger.Info("starting logger metrics reporter")
		go metrics.Log(metrics.DefaultRegistry, time.Minute, log.New(os.Stderr, "metrics: ", log.Lmicroseconds))
	}

	amqpConn, err := amqp.Dial(cfg.AmqpURI)
	if err != nil {
		logger.WithField("err", err).Error("couldn't connect to AMQP")
		return
	}

	go func() {
		errChan := make(chan *amqp.Error)
		errChan = amqpConn.NotifyClose(errChan)

		err, ok := <-errChan
		if ok {
			logger.WithField("err", err).Error("amqp connection errored, terminating")
			cancel()
		}
	}()

	logger.Debug("connected to AMQP")

	generator := worker.NewBuildScriptGenerator(cfg)
	logger.WithFields(logrus.Fields{
		"build_script_generator": fmt.Sprintf("%#v", generator),
	}).Debug("built")

	provider, err := backend.NewProvider(cfg.ProviderName, cfg.ProviderConfig)
	if err != nil {
		logger.WithField("err", err).Error("couldn't create backend provider")
		return
	}
	logger.WithFields(logrus.Fields{
		"provider": fmt.Sprintf("%#v", provider),
	}).Debug("built")

	commandDispatcher := worker.NewCommandDispatcher(ctx, amqpConn)
	logger.WithFields(logrus.Fields{
		"command_dispatcher": fmt.Sprintf("%#v", commandDispatcher),
	}).Debug("built")

	go commandDispatcher.Run()

	pool := worker.NewProcessorPool(cfg.Hostname, ctx, cfg.HardTimeout, amqpConn,
		provider, generator, commandDispatcher)

	pool.SkipShutdownOnLogTimeout = cfg.SkipShutdownOnLogTimeout
	logger.WithFields(logrus.Fields{
		"pool": pool,
	}).Debug("built")

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGTERM, syscall.SIGINT)
	go func() {
		sig := <-signalChan
		if sig == syscall.SIGINT {
			logger.Info("SIGTERM received, starting graceful shutdown")
			pool.GracefulShutdown()
		} else {
			logger.Info("SIGINT received, shutting down immediately")
			cancel()
		}
	}()

	logger.WithFields(logrus.Fields{
		"pool_size":  cfg.PoolSize,
		"queue_name": cfg.QueueName,
	}).Debug("running pool")

	pool.Run(cfg.PoolSize, cfg.QueueName)

	err = amqpConn.Close()
	if err != nil {
		logger.WithField("err", err).Error("couldn't close AMQP connection cleanly")
		return
	}
}
<commit_msg>Adjust signal handling and assoc logging for clarity<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/Sirupsen/logrus/hooks/sentry"
	"github.com/codegangsta/cli"
	"github.com/rcrowley/go-metrics"
	"github.com/rcrowley/go-metrics/librato"
	"github.com/streadway/amqp"
	"github.com/travis-ci/worker"
	"github.com/travis-ci/worker/backend"
	"github.com/travis-ci/worker/config"
	"github.com/travis-ci/worker/context"
	gocontext "golang.org/x/net/context"
)

func main() {
	app := cli.NewApp()
	app.Usage = "Travis Worker daemon"
	app.Version = worker.VersionString
	app.Author = "Travis CI GmbH"
	app.Email = "contact+travis-worker@travis-ci.org"

	app.Flags = config.Flags
	app.Action = runWorker

	app.Run(os.Args)
}

func runWorker(c *cli.Context) {
	ctx, cancel := gocontext.WithCancel(gocontext.Background())
	logger := context.LoggerFromContext(ctx)

	logrus.SetFormatter(&logrus.TextFormatter{DisableColors: true})

	if c.String("pprof-port") != "" {
		// Start net/http/pprof server
		go func() {
			http.ListenAndServe(fmt.Sprintf("localhost:%s", c.String("pprof-port")), nil)
		}()
	}

	if c.Bool("debug") {
		logrus.SetLevel(logrus.DebugLevel)
	}

	cfg := config.ConfigFromCLIContext(c)

	if c.Bool("echo-config") {
		config.WriteEnvConfig(cfg, os.Stdout)
		return
	}

	logger.WithFields(logrus.Fields{
		"cfg": fmt.Sprintf("%#v", cfg),
	}).Debug("read config")

	logger.Info("worker started")
	defer logger.Info("worker finished")

	if cfg.SentryDSN != "" {
		sentryHook, err := logrus_sentry.NewSentryHook(cfg.SentryDSN, []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel})
		if err != nil {
			logger.WithField("err", err).Error("couldn't create sentry hook")
		}

		logrus.AddHook(sentryHook)
	}

	if cfg.LibratoEmail != "" && cfg.LibratoToken != "" && cfg.LibratoSource != "" {
		logger.Info("starting librato metrics reporter")
		go librato.Librato(metrics.DefaultRegistry, time.Minute, cfg.LibratoEmail, cfg.LibratoToken, cfg.LibratoSource, []float64{0.95}, time.Millisecond)
	} else if !c.Bool("silence-metrics") {
		logger.Info("starting logger metrics reporter")
		go metrics.Log(metrics.DefaultRegistry, time.Minute, log.New(os.Stderr, "metrics: ", log.Lmicroseconds))
	}

	amqpConn, err := amqp.Dial(cfg.AmqpURI)
	if err != nil {
		logger.WithField("err", err).Error("couldn't connect to AMQP")
		return
	}

	go func() {
		errChan := make(chan *amqp.Error)
		errChan = amqpConn.NotifyClose(errChan)

		err, ok := <-errChan
		if ok {
			logger.WithField("err", err).Error("amqp connection errored, terminating")
			cancel()
		}
	}()

	logger.Debug("connected to AMQP")

	generator := worker.NewBuildScriptGenerator(cfg)
	logger.WithFields(logrus.Fields{
		"build_script_generator": fmt.Sprintf("%#v", generator),
	}).Debug("built")

	provider, err := backend.NewProvider(cfg.ProviderName, cfg.ProviderConfig)
	if err != nil {
		logger.WithField("err", err).Error("couldn't create backend provider")
		return
	}
	logger.WithFields(logrus.Fields{
		"provider": fmt.Sprintf("%#v", provider),
	}).Debug("built")

	commandDispatcher := worker.NewCommandDispatcher(ctx, amqpConn)
	logger.WithFields(logrus.Fields{
		"command_dispatcher": fmt.Sprintf("%#v", commandDispatcher),
	}).Debug("built")

	go commandDispatcher.Run()

	pool := worker.NewProcessorPool(cfg.Hostname, ctx, cfg.HardTimeout, amqpConn,
		provider, generator, commandDispatcher)

	pool.SkipShutdownOnLogTimeout = cfg.SkipShutdownOnLogTimeout
	logger.WithFields(logrus.Fields{
		"pool": pool,
	}).Debug("built")

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGTERM, syscall.SIGINT)
	go func() {
		sig := <-signalChan
		switch sig {
		case syscall.SIGINT:
			logger.Info("SIGINT received, starting graceful shutdown")
			pool.GracefulShutdown()
		case syscall.SIGTERM:
			logger.Info("SIGTERM received, shutting down immediately")
			cancel()
		default:
			logger.WithField("signal", sig).Info("ignoring unknown signal")
		}
	}()

	logger.WithFields(logrus.Fields{
		"pool_size":  cfg.PoolSize,
		"queue_name": cfg.QueueName,
	}).Debug("running pool")

	pool.Run(cfg.PoolSize, cfg.QueueName)

	err = amqpConn.Close()
	if err != nil {
		logger.WithField("err", err).Error("couldn't close AMQP connection cleanly")
		return
	}
}
<|endoftext|>


<commit_before>package rest

import (
	"github.com/gocraft/web"
	"b00lduck/datalogger/dataservice/orm"
	"net/http"
	"io/ioutil"
	"strconv"
)

// Get all thermometers
func (c *Context) ThermometerHandler(rw web.ResponseWriter, req *web.Request) {
	var thermometers []orm.Counter
	db.Find(&thermometers)
	marshal(rw, thermometers)
}

// Get specific thermometer by code
func (c *Context) ThermometerByCodeHandler(rw web.ResponseWriter, req *web.Request) {

	code := parseStringPathParameter(req, "code")
	var thermometer orm.Thermometer
	db.Where(&orm.Thermometer{Code: code}).First(&thermometer)

	if (thermometer.ID == 0) {
		rw.WriteHeader(http.StatusNotFound)
		rw.Write([]byte("Thermometer not found"))
		return
	}

	marshal(rw, thermometer)
}

// Add thermometer reading by code
func (c *Context) ThermometerByCodeAddReadingHandler(rw web.ResponseWriter, req *web.Request) {

	code := parseStringPathParameter(req, "code")
	var thermometer orm.Thermometer
	db.Where(&orm.Thermometer{Code: code}).First(&thermometer)

	if (thermometer.ID == 0) {
		rw.WriteHeader(http.StatusNotFound)
		rw.Write([]byte("Thermometer not found"))
		return
	}

	body, err := ioutil.ReadAll(req.Body);
	if err != nil {
		rw.WriteHeader(http.StatusInternalServerError)
		rw.Write([]byte("Could not read body"))
		return
	}

	reading, err := strconv.Atoi(string(body))
	if err != nil {
		rw.WriteHeader(http.StatusBadRequest)
		rw.Write([]byte("Could not parse reading"))
		return
	}

	thermometerReading := orm.NewThermometerReading(thermometer, uint64(reading))
	db.Create(&thermometerReading)

	thermometer.Reading = uint64(reading)
	thermometer.LastReading = thermometerReading.Timestamp
	db.Save(thermometer)

	marshal(rw, thermometerReading)
}

// Get thermometer readings in a optionally given time range
// Query parameters: start,end
func (c *Context) ThermometerByCodeGetReadingsHandler(rw web.ResponseWriter, req *web.Request) {

	code := parseStringPathParameter(req, "code")
	var thermometer orm.Thermometer
	db.Where(&orm.Thermometer{Code: code}).First(&thermometer)

	if (thermometer.ID == 0) {
		rw.WriteHeader(http.StatusNotFound)
		rw.Write([]byte("Thermometer not found"))
		return
	}

	start,err := c.parseUintQueryParameter(rw, "start")
	if (err != nil) {
		return
	}

	end,err := c.parseUintQueryParameter(rw, "end")
	if (err != nil) {
		return
	}

	var thermometerReadings []orm.ThermometerReading
	orm.GetOrderedWindowedQuery(db, "thermometer_id", thermometer.ID, start, end).Find(&thermometerReadings)
	marshal(rw, thermometerReadings)
}<commit_msg>DATASERVICE: thermometer readings extend timerange<commit_after>package rest

import (
	"github.com/gocraft/web"
	"b00lduck/datalogger/dataservice/orm"
	"net/http"
	"io/ioutil"
	"strconv"
)

// Get all thermometers
func (c *Context) ThermometerHandler(rw web.ResponseWriter, req *web.Request) {
	var thermometers []orm.Counter
	db.Find(&thermometers)
	marshal(rw, thermometers)
}

// Get specific thermometer by code
func (c *Context) ThermometerByCodeHandler(rw web.ResponseWriter, req *web.Request) {

	code := parseStringPathParameter(req, "code")
	var thermometer orm.Thermometer
	db.Where(&orm.Thermometer{Code: code}).First(&thermometer)

	if (thermometer.ID == 0) {
		rw.WriteHeader(http.StatusNotFound)
		rw.Write([]byte("Thermometer not found"))
		return
	}

	marshal(rw, thermometer)
}

// Add thermometer reading by code
func (c *Context) ThermometerByCodeAddReadingHandler(rw web.ResponseWriter, req *web.Request) {

	code := parseStringPathParameter(req, "code")
	var thermometer orm.Thermometer
	db.Where(&orm.Thermometer{Code: code}).First(&thermometer)

	if (thermometer.ID == 0) {
		rw.WriteHeader(http.StatusNotFound)
		rw.Write([]byte("Thermometer not found"))
		return
	}

	body, err := ioutil.ReadAll(req.Body);
	if err != nil {
		rw.WriteHeader(http.StatusInternalServerError)
		rw.Write([]byte("Could not read body"))
		return
	}

	reading, err := strconv.Atoi(string(body))
	if err != nil {
		rw.WriteHeader(http.StatusBadRequest)
		rw.Write([]byte("Could not parse reading"))
		return
	}

	thermometerReading := orm.NewThermometerReading(thermometer, uint64(reading))
	db.Create(&thermometerReading)

	thermometer.Reading = uint64(reading)
	thermometer.LastReading = thermometerReading.Timestamp
	db.Save(thermometer)

	marshal(rw, thermometerReading)
}

// Get thermometer readings in a optionally given time range
// Query parameters: start,end
func (c *Context) ThermometerByCodeGetReadingsHandler(rw web.ResponseWriter, req *web.Request) {

	code := parseStringPathParameter(req, "code")
	var thermometer orm.Thermometer
	db.Where(&orm.Thermometer{Code: code}).First(&thermometer)

	if (thermometer.ID == 0) {
		rw.WriteHeader(http.StatusNotFound)
		rw.Write([]byte("Thermometer not found"))
		return
	}

	start,err := c.parseUintQueryParameter(rw, "start")
	if (err != nil) {
		return
	}

	end,err := c.parseUintQueryParameter(rw, "end")
	if (err != nil) {
		return
	}

	var thermometerReadings []orm.ThermometerReading
	orm.GetOrderedWindowedQuery(db, "thermometer_id", thermometer.ID, start, end).Find(&thermometerReadings)

	startReading := orm.ThermometerReading{
		Reading: thermometerReadings[0].Reading,
		Timestamp: start,
		ThermometerID: thermometer.ID,
	}

	endReading := orm.ThermometerReading{
		Reading: thermometerReadings[len(thermometerReadings)-1].Reading,
		Timestamp: end,
		ThermometerID: thermometer.ID,
	}

	thermometerReadings = append([]orm.ThermometerReading{startReading}, thermometerReadings...)
	thermometerReadings = append(thermometerReadings, endReading)

	marshal(rw, thermometerReadings)
}<|endoftext|>


<commit_before>package algorithmia

import (
	"errors"
	"net/http"
	"net/url"
	"strings"
)

func getUrl(p string) string {
	return "/v1/data/" + p
}

type datadirClient interface {
	getHelper(url string, params url.Values) (*http.Response, error)
	postJsonHelper(url string, input interface{}, params url.Values) (*http.Response, error)
	deleteHelper(url string) (*http.Response, error)
	patchHelper(url string, params map[string]interface{}) (*http.Response, error)
}

type DataDirectory struct {
	client datadirClient

	Path string
	Url  string
}

func NewDataDirectory(client datadirClient, dataUrl string) *DataDirectory {
	p := strings.TrimSpace(dataUrl)
	if strings.HasPrefix(p, "data://") {
		p = p[len("data://"):]
	} else if strings.HasPrefix(p, "/") {
		p = p[1:]
	}
	return &DataDirectory{
		client: client,
		Path:   p,
		Url:    getUrl(p),
	}
}

func (f *DataDirectory) Exists() (bool, error) {
	resp, err := f.client.getHelper(f.Url, url.Values{})
	return resp.StatusCode == http.StatusOK, err
}

func (f *DataDirectory) Name() (string, error) {
	_, name, err := getParentAndBase(f.Path)
	return name, err
}

func (f *DataDirectory) Create(acl *Acl) error {
	parent, name, err := getParentAndBase(f.Path)
	if err != nil {
		return err
	}
	jso := map[string]interface{}{
		"name": name,
	}
	if acl != nil {
		jso["acl"] = acl.ApiParam()
	}

	resp, err := f.client.postJsonHelper(getUrl(parent), jso, nil)

	if err != nil {
		return err
	}

	if resp.StatusCode != http.StatusOK {
		b, err := getRaw(resp)
		if err != nil {
			return err
		}
		return errors.New("Directory creation failed: " + string(b))
	}
	return nil
}

func (f *DataDirectory) doDelete(force bool) error {
	url := f.Url
	if force {
		url += "?force=true"
	}

	resp, err := f.client.deleteHelper(url)
	if err != nil {
		return err
	}

	b, err := getRaw(resp)
	if err != nil {
		return err
	}

	err = ErrorFromJsonData(b)
	if err != nil {
		return err
	}

	return nil
}

func (f *DataDirectory) Delete() error {
	return f.doDelete(false)
}

func (f *DataDirectory) ForceDelete() error {
	return f.doDelete(true)
}

func (f *DataDirectory) File(name string) *DataFile {
	return NewDataFile(f.client.(*Client), PathJoin(f.Path, name))
}

func (f *DataDirectory) Dir(name string) *DataDirectory {
	return NewDataDirectory(f.client.(*Client), PathJoin(f.Path, name))
}
<commit_msg>DataDirectory coding<commit_after>package algorithmia

import (
	"errors"
	"net/http"
	"net/url"
	"strings"

	"github.com/mitchellh/mapstructure"
)

func getUrl(p string) string {
	return "/v1/data/" + p
}

type datadirClient interface {
	getHelper(url string, params url.Values) (*http.Response, error)
	postJsonHelper(url string, input interface{}, params url.Values) (*http.Response, error)
	deleteHelper(url string) (*http.Response, error)
	patchHelper(url string, params map[string]interface{}) (*http.Response, error)
}

type DataDirectory struct {
	client datadirClient

	Path string
	Url  string
}

func NewDataDirectory(client datadirClient, dataUrl string) *DataDirectory {
	p := strings.TrimSpace(dataUrl)
	if strings.HasPrefix(p, "data://") {
		p = p[len("data://"):]
	} else if strings.HasPrefix(p, "/") {
		p = p[1:]
	}
	return &DataDirectory{
		client: client,
		Path:   p,
		Url:    getUrl(p),
	}
}

func (f *DataDirectory) Exists() (bool, error) {
	resp, err := f.client.getHelper(f.Url, url.Values{})
	return resp.StatusCode == http.StatusOK, err
}

func (f *DataDirectory) Name() (string, error) {
	_, name, err := getParentAndBase(f.Path)
	return name, err
}

func (f *DataDirectory) Create(acl *Acl) error {
	parent, name, err := getParentAndBase(f.Path)
	if err != nil {
		return err
	}
	jso := map[string]interface{}{
		"name": name,
	}
	if acl != nil {
		jso["acl"] = acl.ApiParam()
	}

	resp, err := f.client.postJsonHelper(getUrl(parent), jso, nil)

	if err != nil {
		return err
	}

	if resp.StatusCode != http.StatusOK {
		b, err := getRaw(resp)
		if err != nil {
			return err
		}
		return errors.New("Directory creation failed: " + string(b))
	}
	return nil
}

func (f *DataDirectory) doDelete(force bool) error {
	url := f.Url
	if force {
		url += "?force=true"
	}

	resp, err := f.client.deleteHelper(url)
	if err != nil {
		return err
	}

	b, err := getRaw(resp)
	if err != nil {
		return err
	}

	err = ErrorFromJsonData(b)
	if err != nil {
		return err
	}

	return nil
}

func (f *DataDirectory) Delete() error {
	return f.doDelete(false)
}

func (f *DataDirectory) ForceDelete() error {
	return f.doDelete(true)
}

func (f *DataDirectory) File(name string) *DataFile {
	return NewDataFile(f.client.(*Client), PathJoin(f.Path, name))
}

func (f *DataDirectory) Dir(name string) *DataDirectory {
	return NewDataDirectory(f.client.(*Client), PathJoin(f.Path, name))
}

func (f *DataDirectory) Permissions() (*Acl, error) {
	v := url.Values{}
	v.Add("acl", "true")
	resp, err := f.client.getHelper(f.Url, v)
	if err != nil {
		return nil, err
	}
	var m map[string]interface{}
	err = getJson(resp, &m)
	if err != nil {
		return nil, err
	}
	if aclr, ok := m["acl"]; ok {
		var aclResp AclResponse
		if err := mapstructure.Decode(aclr, &aclResp); err == nil {
			return AclFromResponse(&aclResp)
		} else {
			return nil, err
		}
	}
	return nil, nil
}

func (f *DataDirectory) UpdatePermissions(acl *Acl) error {
	params := map[string]interface{}{
		"acl": acl.ApiParam(),
	}
	resp, err := f.client.patchHelper(f.Url, params)
	if err != nil {
		return err
	}
	if resp.StatusCode != http.StatusOK {
		b, err := getRaw(resp)
		if err != nil {
			return err
		}
		return ErrorFromJsonData(b)
	}
	return nil
}
<|endoftext|>