<commit_before>// Copyright 2014 shiena Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// +build windows

package ansicolor

import (
	"bytes"
	"io"
	"strings"
	"syscall"
	"unsafe"
)

type csiState int

const (
	outsideCsiCode csiState = iota
	firstCsiCode
	secondCsiCode
)

type parseResult int

const (
	noConsole parseResult = iota
	changedColor
	unknown
)

type ansiColorWriter struct {
	w             io.Writer
	mode          outputMode
	state         csiState
	paramStartBuf bytes.Buffer
	paramBuf      bytes.Buffer
}

const (
	firstCsiChar   byte = '\x1b'
	secondeCsiChar byte = '['
	separatorChar  byte = ';'
	sgrCode        byte = 'm'
)

const (
	foregroundBlue      = uint16(0x0001)
	foregroundGreen     = uint16(0x0002)
	foregroundRed       = uint16(0x0004)
	foregroundIntensity = uint16(0x0008)
	backgroundBlue      = uint16(0x0010)
	backgroundGreen     = uint16(0x0020)
	backgroundRed       = uint16(0x0040)
	backgroundIntensity = uint16(0x0080)
	underscore          = uint16(0x8000)

	foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity
	backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity
)

const (
	ansiReset        = "0"
	ansiIntensityOn  = "1"
	ansiIntensityOff = "21"
	ansiUnderlineOn  = "4"
	ansiUnderlineOff = "24"
	ansiBlinkOn      = "5"
	ansiBlinkOff     = "25"

	ansiForegroundBlack   = "30"
	ansiForegroundRed     = "31"
	ansiForegroundGreen   = "32"
	ansiForegroundYellow  = "33"
	ansiForegroundBlue    = "34"
	ansiForegroundMagenta = "35"
	ansiForegroundCyan    = "36"
	ansiForegroundWhite   = "37"
	ansiForegroundDefault = "39"

	ansiBackgroundBlack   = "40"
	ansiBackgroundRed     = "41"
	ansiBackgroundGreen   = "42"
	ansiBackgroundYellow  = "43"
	ansiBackgroundBlue    = "44"
	ansiBackgroundMagenta = "45"
	ansiBackgroundCyan    = "46"
	ansiBackgroundWhite   = "47"
	ansiBackgroundDefault = "49"

	ansiLightForegroundGray    = "90"
	ansiLightForegroundRed     = "91"
	ansiLightForegroundGreen   = "92"
	ansiLightForegroundYellow  = "93"
	ansiLightForegroundBlue    = "94"
	ansiLightForegroundMagenta = "95"
	ansiLightForegroundCyan    = "96"
	ansiLightForegroundWhite   = "97"

	ansiLightBackgroundGray    = "100"
	ansiLightBackgroundRed     = "101"
	ansiLightBackgroundGreen   = "102"
	ansiLightBackgroundYellow  = "103"
	ansiLightBackgroundBlue    = "104"
	ansiLightBackgroundMagenta = "105"
	ansiLightBackgroundCyan    = "106"
	ansiLightBackgroundWhite   = "107"
)

type drawType int

const (
	foreground drawType = iota
	background
)

type winColor struct {
	code     uint16
	drawType drawType
}

var colorMap = map[string]winColor{
	ansiForegroundBlack:   {0, foreground},
	ansiForegroundRed:     {foregroundRed, foreground},
	ansiForegroundGreen:   {foregroundGreen, foreground},
	ansiForegroundYellow:  {foregroundRed | foregroundGreen, foreground},
	ansiForegroundBlue:    {foregroundBlue, foreground},
	ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground},
	ansiForegroundCyan:    {foregroundGreen | foregroundBlue, foreground},
	ansiForegroundWhite:   {foregroundRed | foregroundGreen | foregroundBlue, foreground},
	ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground},

	ansiBackgroundBlack:   {0, background},
	ansiBackgroundRed:     {backgroundRed, background},
	ansiBackgroundGreen:   {backgroundGreen, background},
	ansiBackgroundYellow:  {backgroundRed | backgroundGreen, background},
	ansiBackgroundBlue:    {backgroundBlue, background},
	ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background},
	ansiBackgroundCyan:    {backgroundGreen | backgroundBlue, background},
	ansiBackgroundWhite:   {backgroundRed | backgroundGreen | backgroundBlue, background},
	ansiBackgroundDefault: {0, background},

	ansiLightForegroundGray:    {foregroundIntensity, foreground},
	ansiLightForegroundRed:     {foregroundIntensity | foregroundRed, foreground},
	ansiLightForegroundGreen:   {foregroundIntensity | foregroundGreen, foreground},
	ansiLightForegroundYellow:  {foregroundIntensity | foregroundRed | foregroundGreen, foreground},
	ansiLightForegroundBlue:    {foregroundIntensity | foregroundBlue, foreground},
	ansiLightForegroundMagenta: {foregroundIntensity | foregroundRed | foregroundBlue, foreground},
	ansiLightForegroundCyan:    {foregroundIntensity | foregroundGreen | foregroundBlue, foreground},
	ansiLightForegroundWhite:   {foregroundIntensity | foregroundRed | foregroundGreen | foregroundBlue, foreground},

	ansiLightBackgroundGray:    {backgroundIntensity, background},
	ansiLightBackgroundRed:     {backgroundIntensity | backgroundRed, background},
	ansiLightBackgroundGreen:   {backgroundIntensity | backgroundGreen, background},
	ansiLightBackgroundYellow:  {backgroundIntensity | backgroundRed | backgroundGreen, background},
	ansiLightBackgroundBlue:    {backgroundIntensity | backgroundBlue, background},
	ansiLightBackgroundMagenta: {backgroundIntensity | backgroundRed | backgroundBlue, background},
	ansiLightBackgroundCyan:    {backgroundIntensity | backgroundGreen | backgroundBlue, background},
	ansiLightBackgroundWhite:   {backgroundIntensity | backgroundRed | backgroundGreen | backgroundBlue, background},
}

var (
	kernel32                       = syscall.NewLazyDLL("kernel32.dll")
	procSetConsoleTextAttribute    = kernel32.NewProc("SetConsoleTextAttribute")
	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
	defaultAttr                    *textAttributes
)

func init() {
	screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
	if screenInfo != nil {
		colorMap[ansiForegroundDefault] = winColor{
			screenInfo.WAttributes & (foregroundRed | foregroundGreen | foregroundBlue),
			foreground,
		}
		colorMap[ansiBackgroundDefault] = winColor{
			screenInfo.WAttributes & (backgroundRed | backgroundGreen | backgroundBlue),
			background,
		}
		defaultAttr = convertTextAttr(screenInfo.WAttributes)
	}
}

type coord struct {
	X, Y int16
}

type smallRect struct {
	Left, Top, Right, Bottom int16
}

type consoleScreenBufferInfo struct {
	DwSize              coord
	DwCursorPosition    coord
	WAttributes         uint16
	SrWindow            smallRect
	DwMaximumWindowSize coord
}

func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo {
	var csbi consoleScreenBufferInfo
	ret, _, _ := procGetConsoleScreenBufferInfo.Call(
		hConsoleOutput,
		uintptr(unsafe.Pointer(&csbi)))
	if ret == 0 {
		return nil
	}
	return &csbi
}

func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool {
	ret, _, _ := procSetConsoleTextAttribute.Call(
		hConsoleOutput,
		uintptr(wAttributes))
	return ret != 0
}

type textAttributes struct {
	foregroundColor     uint16
	backgroundColor     uint16
	foregroundIntensity uint16
	backgroundIntensity uint16
	underscore          uint16
	otherAttributes     uint16
}

func convertTextAttr(winAttr uint16) *textAttributes {
	fgColor := winAttr & (foregroundRed | foregroundGreen | foregroundBlue)
	bgColor := winAttr & (backgroundRed | backgroundGreen | backgroundBlue)
	fgIntensity := winAttr & foregroundIntensity
	bgIntensity := winAttr & backgroundIntensity
	underline := winAttr & underscore
	otherAttributes := winAttr &^ (foregroundMask | backgroundMask | underscore)
	return &textAttributes{fgColor, bgColor, fgIntensity, bgIntensity, underline, otherAttributes}
}

func convertWinAttr(textAttr *textAttributes) uint16 {
	var winAttr uint16
	winAttr |= textAttr.foregroundColor
	winAttr |= textAttr.backgroundColor
	winAttr |= textAttr.foregroundIntensity
	winAttr |= textAttr.backgroundIntensity
	winAttr |= textAttr.underscore
	winAttr |= textAttr.otherAttributes
	return winAttr
}

func changeColor(param []byte) parseResult {
	screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
	if screenInfo == nil {
		return noConsole
	}

	winAttr := convertTextAttr(screenInfo.WAttributes)
	strParam := string(param)
	if len(strParam) <= 0 {
		strParam = "0"
	}
	csiParam := strings.Split(strParam, string(separatorChar))
	for _, p := range csiParam {
		c, ok := colorMap[p]
		switch {
		case !ok:
			switch p {
			case ansiReset:
				winAttr.foregroundColor = defaultAttr.foregroundColor
				winAttr.backgroundColor = defaultAttr.backgroundColor
				winAttr.foregroundIntensity = defaultAttr.foregroundIntensity
				winAttr.backgroundIntensity = defaultAttr.backgroundIntensity
				winAttr.underscore = 0
				winAttr.otherAttributes = 0
			case ansiIntensityOn:
				winAttr.foregroundIntensity = foregroundIntensity
			case ansiIntensityOff:
				winAttr.foregroundIntensity = 0
			case ansiUnderlineOn:
				winAttr.underscore = underscore
			case ansiUnderlineOff:
				winAttr.underscore = 0
			case ansiBlinkOn:
				winAttr.backgroundIntensity = backgroundIntensity
			case ansiBlinkOff:
				winAttr.backgroundIntensity = 0
			default:
				// unknown code
			}
		case c.drawType == foreground:
			winAttr.foregroundColor = c.code
		case c.drawType == background:
			winAttr.backgroundColor = c.code
		}
	}
	winTextAttribute := convertWinAttr(winAttr)
	setConsoleTextAttribute(uintptr(syscall.Stdout), winTextAttribute)

	return changedColor
}

func parseEscapeSequence(command byte, param []byte) parseResult {
	if defaultAttr == nil {
		return noConsole
	}

	switch command {
	case sgrCode:
		return changeColor(param)
	default:
		return unknown
	}
}

func (cw *ansiColorWriter) flushBuffer() (int, error) {
	return cw.flushTo(cw.w)
}

func (cw *ansiColorWriter) resetBuffer() (int, error) {
	return cw.flushTo(nil)
}

func (cw *ansiColorWriter) flushTo(w io.Writer) (int, error) {
	var n1, n2 int
	var err error

	startBytes := cw.paramStartBuf.Bytes()
	cw.paramStartBuf.Reset()
	if w != nil {
		n1, err = cw.w.Write(startBytes)
		if err != nil {
			return n1, err
		}
	} else {
		n1 = len(startBytes)
	}
	paramBytes := cw.paramBuf.Bytes()
	cw.paramBuf.Reset()
	if w != nil {
		n2, err = cw.w.Write(paramBytes)
		if err != nil {
			return n1 + n2, err
		}
	} else {
		n2 = len(paramBytes)
	}
	return n1 + n2, nil
}

func isParameterChar(b byte) bool {
	return ('0' <= b && b <= '9') || b == separatorChar
}

func (cw *ansiColorWriter) Write(p []byte) (int, error) {
	r, nw, first, last := 0, 0, 0, 0
	if cw.mode != DiscardNonColorEscSeq {
		cw.state = outsideCsiCode
		cw.resetBuffer()
	}

	var err error
	for i, ch := range p {
		switch cw.state {
		case outsideCsiCode:
			if ch == firstCsiChar {
				cw.paramStartBuf.WriteByte(ch)
				cw.state = firstCsiCode
			}
		case firstCsiCode:
			switch ch {
			case firstCsiChar:
				cw.paramStartBuf.WriteByte(ch)
				break
			case secondeCsiChar:
				cw.paramStartBuf.WriteByte(ch)
				cw.state = secondCsiCode
				last = i - 1
			default:
				cw.resetBuffer()
				cw.state = outsideCsiCode
			}
		case secondCsiCode:
			if isParameterChar(ch) {
				cw.paramBuf.WriteByte(ch)
			} else {
				nw, err = cw.w.Write(p[first:last])
				r += nw
				if err != nil {
					return r, err
				}
				first = i + 1
				result := parseEscapeSequence(ch, cw.paramBuf.Bytes())
				if result == noConsole || (cw.mode == OutputNonColorEscSeq && result == unknown) {
					cw.paramBuf.WriteByte(ch)
					nw, err := cw.flushBuffer()
					if err != nil {
						return r, err
					}
					r += nw
				} else {
					n, _ := cw.resetBuffer()
					// Add one more to the size of the buffer for the last ch
					r += n + 1
				}

				cw.state = outsideCsiCode
			}
		default:
			cw.state = outsideCsiCode
		}
	}

	if cw.mode != DiscardNonColorEscSeq || cw.state == outsideCsiCode {
		nw, err = cw.w.Write(p[first:len(p)])
		r += nw
	}

	return r, err
}
<commit_msg>gofmt -s<commit_after>// Copyright 2014 shiena Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// +build windows

package ansicolor

import (
	"bytes"
	"io"
	"strings"
	"syscall"
	"unsafe"
)

type csiState int

const (
	outsideCsiCode csiState = iota
	firstCsiCode
	secondCsiCode
)

type parseResult int

const (
	noConsole parseResult = iota
	changedColor
	unknown
)

type ansiColorWriter struct {
	w             io.Writer
	mode          outputMode
	state         csiState
	paramStartBuf bytes.Buffer
	paramBuf      bytes.Buffer
}

const (
	firstCsiChar   byte = '\x1b'
	secondeCsiChar byte = '['
	separatorChar  byte = ';'
	sgrCode        byte = 'm'
)

const (
	foregroundBlue      = uint16(0x0001)
	foregroundGreen     = uint16(0x0002)
	foregroundRed       = uint16(0x0004)
	foregroundIntensity = uint16(0x0008)
	backgroundBlue      = uint16(0x0010)
	backgroundGreen     = uint16(0x0020)
	backgroundRed       = uint16(0x0040)
	backgroundIntensity = uint16(0x0080)
	underscore          = uint16(0x8000)

	foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity
	backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity
)

const (
	ansiReset        = "0"
	ansiIntensityOn  = "1"
	ansiIntensityOff = "21"
	ansiUnderlineOn  = "4"
	ansiUnderlineOff = "24"
	ansiBlinkOn      = "5"
	ansiBlinkOff     = "25"

	ansiForegroundBlack   = "30"
	ansiForegroundRed     = "31"
	ansiForegroundGreen   = "32"
	ansiForegroundYellow  = "33"
	ansiForegroundBlue    = "34"
	ansiForegroundMagenta = "35"
	ansiForegroundCyan    = "36"
	ansiForegroundWhite   = "37"
	ansiForegroundDefault = "39"

	ansiBackgroundBlack   = "40"
	ansiBackgroundRed     = "41"
	ansiBackgroundGreen   = "42"
	ansiBackgroundYellow  = "43"
	ansiBackgroundBlue    = "44"
	ansiBackgroundMagenta = "45"
	ansiBackgroundCyan    = "46"
	ansiBackgroundWhite   = "47"
	ansiBackgroundDefault = "49"

	ansiLightForegroundGray    = "90"
	ansiLightForegroundRed     = "91"
	ansiLightForegroundGreen   = "92"
	ansiLightForegroundYellow  = "93"
	ansiLightForegroundBlue    = "94"
	ansiLightForegroundMagenta = "95"
	ansiLightForegroundCyan    = "96"
	ansiLightForegroundWhite   = "97"

	ansiLightBackgroundGray    = "100"
	ansiLightBackgroundRed     = "101"
	ansiLightBackgroundGreen   = "102"
	ansiLightBackgroundYellow  = "103"
	ansiLightBackgroundBlue    = "104"
	ansiLightBackgroundMagenta = "105"
	ansiLightBackgroundCyan    = "106"
	ansiLightBackgroundWhite   = "107"
)

type drawType int

const (
	foreground drawType = iota
	background
)

type winColor struct {
	code     uint16
	drawType drawType
}

var colorMap = map[string]winColor{
	ansiForegroundBlack:   {0, foreground},
	ansiForegroundRed:     {foregroundRed, foreground},
	ansiForegroundGreen:   {foregroundGreen, foreground},
	ansiForegroundYellow:  {foregroundRed | foregroundGreen, foreground},
	ansiForegroundBlue:    {foregroundBlue, foreground},
	ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground},
	ansiForegroundCyan:    {foregroundGreen | foregroundBlue, foreground},
	ansiForegroundWhite:   {foregroundRed | foregroundGreen | foregroundBlue, foreground},
	ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground},

	ansiBackgroundBlack:   {0, background},
	ansiBackgroundRed:     {backgroundRed, background},
	ansiBackgroundGreen:   {backgroundGreen, background},
	ansiBackgroundYellow:  {backgroundRed | backgroundGreen, background},
	ansiBackgroundBlue:    {backgroundBlue, background},
	ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background},
	ansiBackgroundCyan:    {backgroundGreen | backgroundBlue, background},
	ansiBackgroundWhite:   {backgroundRed | backgroundGreen | backgroundBlue, background},
	ansiBackgroundDefault: {0, background},

	ansiLightForegroundGray:    {foregroundIntensity, foreground},
	ansiLightForegroundRed:     {foregroundIntensity | foregroundRed, foreground},
	ansiLightForegroundGreen:   {foregroundIntensity | foregroundGreen, foreground},
	ansiLightForegroundYellow:  {foregroundIntensity | foregroundRed | foregroundGreen, foreground},
	ansiLightForegroundBlue:    {foregroundIntensity | foregroundBlue, foreground},
	ansiLightForegroundMagenta: {foregroundIntensity | foregroundRed | foregroundBlue, foreground},
	ansiLightForegroundCyan:    {foregroundIntensity | foregroundGreen | foregroundBlue, foreground},
	ansiLightForegroundWhite:   {foregroundIntensity | foregroundRed | foregroundGreen | foregroundBlue, foreground},

	ansiLightBackgroundGray:    {backgroundIntensity, background},
	ansiLightBackgroundRed:     {backgroundIntensity | backgroundRed, background},
	ansiLightBackgroundGreen:   {backgroundIntensity | backgroundGreen, background},
	ansiLightBackgroundYellow:  {backgroundIntensity | backgroundRed | backgroundGreen, background},
	ansiLightBackgroundBlue:    {backgroundIntensity | backgroundBlue, background},
	ansiLightBackgroundMagenta: {backgroundIntensity | backgroundRed | backgroundBlue, background},
	ansiLightBackgroundCyan:    {backgroundIntensity | backgroundGreen | backgroundBlue, background},
	ansiLightBackgroundWhite:   {backgroundIntensity | backgroundRed | backgroundGreen | backgroundBlue, background},
}

var (
	kernel32                       = syscall.NewLazyDLL("kernel32.dll")
	procSetConsoleTextAttribute    = kernel32.NewProc("SetConsoleTextAttribute")
	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
	defaultAttr                    *textAttributes
)

func init() {
	screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
	if screenInfo != nil {
		colorMap[ansiForegroundDefault] = winColor{
			screenInfo.WAttributes & (foregroundRed | foregroundGreen | foregroundBlue),
			foreground,
		}
		colorMap[ansiBackgroundDefault] = winColor{
			screenInfo.WAttributes & (backgroundRed | backgroundGreen | backgroundBlue),
			background,
		}
		defaultAttr = convertTextAttr(screenInfo.WAttributes)
	}
}

type coord struct {
	X, Y int16
}

type smallRect struct {
	Left, Top, Right, Bottom int16
}

type consoleScreenBufferInfo struct {
	DwSize              coord
	DwCursorPosition    coord
	WAttributes         uint16
	SrWindow            smallRect
	DwMaximumWindowSize coord
}

func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo {
	var csbi consoleScreenBufferInfo
	ret, _, _ := procGetConsoleScreenBufferInfo.Call(
		hConsoleOutput,
		uintptr(unsafe.Pointer(&csbi)))
	if ret == 0 {
		return nil
	}
	return &csbi
}

func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool {
	ret, _, _ := procSetConsoleTextAttribute.Call(
		hConsoleOutput,
		uintptr(wAttributes))
	return ret != 0
}

type textAttributes struct {
	foregroundColor     uint16
	backgroundColor     uint16
	foregroundIntensity uint16
	backgroundIntensity uint16
	underscore          uint16
	otherAttributes     uint16
}

func convertTextAttr(winAttr uint16) *textAttributes {
	fgColor := winAttr & (foregroundRed | foregroundGreen | foregroundBlue)
	bgColor := winAttr & (backgroundRed | backgroundGreen | backgroundBlue)
	fgIntensity := winAttr & foregroundIntensity
	bgIntensity := winAttr & backgroundIntensity
	underline := winAttr & underscore
	otherAttributes := winAttr &^ (foregroundMask | backgroundMask | underscore)
	return &textAttributes{fgColor, bgColor, fgIntensity, bgIntensity, underline, otherAttributes}
}

func convertWinAttr(textAttr *textAttributes) uint16 {
	var winAttr uint16
	winAttr |= textAttr.foregroundColor
	winAttr |= textAttr.backgroundColor
	winAttr |= textAttr.foregroundIntensity
	winAttr |= textAttr.backgroundIntensity
	winAttr |= textAttr.underscore
	winAttr |= textAttr.otherAttributes
	return winAttr
}

func changeColor(param []byte) parseResult {
	screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
	if screenInfo == nil {
		return noConsole
	}

	winAttr := convertTextAttr(screenInfo.WAttributes)
	strParam := string(param)
	if len(strParam) <= 0 {
		strParam = "0"
	}
	csiParam := strings.Split(strParam, string(separatorChar))
	for _, p := range csiParam {
		c, ok := colorMap[p]
		switch {
		case !ok:
			switch p {
			case ansiReset:
				winAttr.foregroundColor = defaultAttr.foregroundColor
				winAttr.backgroundColor = defaultAttr.backgroundColor
				winAttr.foregroundIntensity = defaultAttr.foregroundIntensity
				winAttr.backgroundIntensity = defaultAttr.backgroundIntensity
				winAttr.underscore = 0
				winAttr.otherAttributes = 0
			case ansiIntensityOn:
				winAttr.foregroundIntensity = foregroundIntensity
			case ansiIntensityOff:
				winAttr.foregroundIntensity = 0
			case ansiUnderlineOn:
				winAttr.underscore = underscore
			case ansiUnderlineOff:
				winAttr.underscore = 0
			case ansiBlinkOn:
				winAttr.backgroundIntensity = backgroundIntensity
			case ansiBlinkOff:
				winAttr.backgroundIntensity = 0
			default:
				// unknown code
			}
		case c.drawType == foreground:
			winAttr.foregroundColor = c.code
		case c.drawType == background:
			winAttr.backgroundColor = c.code
		}
	}
	winTextAttribute := convertWinAttr(winAttr)
	setConsoleTextAttribute(uintptr(syscall.Stdout), winTextAttribute)

	return changedColor
}

func parseEscapeSequence(command byte, param []byte) parseResult {
	if defaultAttr == nil {
		return noConsole
	}

	switch command {
	case sgrCode:
		return changeColor(param)
	default:
		return unknown
	}
}

func (cw *ansiColorWriter) flushBuffer() (int, error) {
	return cw.flushTo(cw.w)
}

func (cw *ansiColorWriter) resetBuffer() (int, error) {
	return cw.flushTo(nil)
}

func (cw *ansiColorWriter) flushTo(w io.Writer) (int, error) {
	var n1, n2 int
	var err error

	startBytes := cw.paramStartBuf.Bytes()
	cw.paramStartBuf.Reset()
	if w != nil {
		n1, err = cw.w.Write(startBytes)
		if err != nil {
			return n1, err
		}
	} else {
		n1 = len(startBytes)
	}
	paramBytes := cw.paramBuf.Bytes()
	cw.paramBuf.Reset()
	if w != nil {
		n2, err = cw.w.Write(paramBytes)
		if err != nil {
			return n1 + n2, err
		}
	} else {
		n2 = len(paramBytes)
	}
	return n1 + n2, nil
}

func isParameterChar(b byte) bool {
	return ('0' <= b && b <= '9') || b == separatorChar
}

func (cw *ansiColorWriter) Write(p []byte) (int, error) {
	r, nw, first, last := 0, 0, 0, 0
	if cw.mode != DiscardNonColorEscSeq {
		cw.state = outsideCsiCode
		cw.resetBuffer()
	}

	var err error
	for i, ch := range p {
		switch cw.state {
		case outsideCsiCode:
			if ch == firstCsiChar {
				cw.paramStartBuf.WriteByte(ch)
				cw.state = firstCsiCode
			}
		case firstCsiCode:
			switch ch {
			case firstCsiChar:
				cw.paramStartBuf.WriteByte(ch)
				break
			case secondeCsiChar:
				cw.paramStartBuf.WriteByte(ch)
				cw.state = secondCsiCode
				last = i - 1
			default:
				cw.resetBuffer()
				cw.state = outsideCsiCode
			}
		case secondCsiCode:
			if isParameterChar(ch) {
				cw.paramBuf.WriteByte(ch)
			} else {
				nw, err = cw.w.Write(p[first:last])
				r += nw
				if err != nil {
					return r, err
				}
				first = i + 1
				result := parseEscapeSequence(ch, cw.paramBuf.Bytes())
				if result == noConsole || (cw.mode == OutputNonColorEscSeq && result == unknown) {
					cw.paramBuf.WriteByte(ch)
					nw, err := cw.flushBuffer()
					if err != nil {
						return r, err
					}
					r += nw
				} else {
					n, _ := cw.resetBuffer()
					// Add one more to the size of the buffer for the last ch
					r += n + 1
				}

				cw.state = outsideCsiCode
			}
		default:
			cw.state = outsideCsiCode
		}
	}

	if cw.mode != DiscardNonColorEscSeq || cw.state == outsideCsiCode {
		nw, err = cw.w.Write(p[first:])
		r += nw
	}

	return r, err
}
<|endoftext|>


<commit_before>package reform

import (
	"database/sql"
	"fmt"
	"strings"
	"time"
)

// DBInterface is a subset of *sql.DB used by reform.
// Can be used together with NewDBFromInterface for easier integration with existing code or for passing test doubles.
type DBInterface interface {
	DBTX
	Begin() (*sql.Tx, error)
}

// check interface
var _ DBInterface = (*sql.DB)(nil)

// DB represents a connection to SQL database.
type DB struct {
	*Querier
	db DBInterface
}

// NewDB creates new DB object for given SQL database connection.
func NewDB(db *sql.DB, dialect Dialect, logger Logger) *DB {
	return NewDBFromInterface(db, dialect, logger)
}

// NewDBFromInterface creates new DB object for given DBInterface.
// Can be used for easier integration with existing code or for passing test doubles.
func NewDBFromInterface(db DBInterface, dialect Dialect, logger Logger) *DB {
	newDB := DB{db: db}
	newDB.Querier = newQuerier(db, dialect, logger, &newDB)
	return &newDB
}

// DBInterface returns DBInterface associated with a given DB object.
func (db *DB) DBInterface() DBInterface {
	return db.db
}

// Begin starts a transaction.
func (db *DB) Begin() (*TX, error) {
	db.logBefore("BEGIN", nil)
	start := time.Now()
	tx, err := db.db.Begin()
	db.logAfter("BEGIN", nil, time.Since(start), err)
	if err != nil {
		return nil, err
	}
	return NewTX(tx, db.Dialect, db.Logger, db), nil
}

// InTransaction wraps function execution in transaction, rolling back it in case of error or panic,
// committing otherwise.
func (db *DB) InTransaction(f func(t *TX) error) error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}

	var committed bool
	defer func() {
		if !committed {
			// always return f() or Commit() error, not possible Rollback() error
			_ = tx.Rollback()
		}
	}()

	err = f(tx)
	if err == nil {
		err = tx.Commit()
	}
	if err == nil {
		committed = true
	}
	return err
}

// OperatorAndPlaceholderOfValueForSQL generates an operator and placeholder for a value intor a condition into SQL query (for exampel "= ?") for the first argument of sql.Exec()
func (db DB) OperatorAndPlaceholderOfValueForSQL(valueI interface{}, placeholderCounter int) string {
	switch valueI.(type) {
	case []int, []string, []float32, []float64, []int64:
		return " IN ("+db.Dialect.Placeholder(placeholderCounter)+")"
	case int, string, float32, float64, int64:
		return " = "+db.Dialect.Placeholder(placeholderCounter)
	case nil:
		return " IS NULL"
	default:
		return " = "+db.Dialect.Placeholder(placeholderCounter)
	}
}

// ValueForSQL generates the value argument for sql.Exec() [not-the-first arguments]
func (db DB) ValueForSQL(valueI interface{}) interface{} {
	switch value := valueI.(type) {
	case []int, []string, []float32, []float64, []int64:
		return strings.Replace(fmt.Sprintf("%v", value), ` `, `" "`, -1)
	case int, string, float32, float64, int64:
		return value
	case nil:
		return nil
	default:
		stringer, ok := value.(Stringer)
		if !ok {
			return fmt.Sprintf("%v", value)
		} else {
			return stringer.String()
		}
	}
}

// check interface
var _ DBTX = (*DB)(nil)
<commit_msg>A bugfix for b8bbb22125884ae7d90538da46f76437ee2dde45<commit_after>package reform

import (
	"database/sql"
	"fmt"
	"strings"
	"time"
)

// DBInterface is a subset of *sql.DB used by reform.
// Can be used together with NewDBFromInterface for easier integration with existing code or for passing test doubles.
type DBInterface interface {
	DBTX
	Begin() (*sql.Tx, error)
}

// check interface
var _ DBInterface = (*sql.DB)(nil)

// DB represents a connection to SQL database.
type DB struct {
	*Querier
	db DBInterface
}

// NewDB creates new DB object for given SQL database connection.
func NewDB(db *sql.DB, dialect Dialect, logger Logger) *DB {
	return NewDBFromInterface(db, dialect, logger)
}

// NewDBFromInterface creates new DB object for given DBInterface.
// Can be used for easier integration with existing code or for passing test doubles.
func NewDBFromInterface(db DBInterface, dialect Dialect, logger Logger) *DB {
	newDB := DB{db: db}
	newDB.Querier = newQuerier(db, dialect, logger, &newDB)
	return &newDB
}

// DBInterface returns DBInterface associated with a given DB object.
func (db *DB) DBInterface() DBInterface {
	return db.db
}

// Begin starts a transaction.
func (db *DB) Begin() (*TX, error) {
	db.logBefore("BEGIN", nil)
	start := time.Now()
	tx, err := db.db.Begin()
	db.logAfter("BEGIN", nil, time.Since(start), err)
	if err != nil {
		return nil, err
	}
	return NewTX(tx, db.Dialect, db.Logger, db), nil
}

// InTransaction wraps function execution in transaction, rolling back it in case of error or panic,
// committing otherwise.
func (db *DB) InTransaction(f func(t *TX) error) error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}

	var committed bool
	defer func() {
		if !committed {
			// always return f() or Commit() error, not possible Rollback() error
			_ = tx.Rollback()
		}
	}()

	err = f(tx)
	if err == nil {
		err = tx.Commit()
	}
	if err == nil {
		committed = true
	}
	return err
}

// OperatorAndPlaceholderOfValueForSQL generates an operator and placeholder for a value intor a condition into SQL query (for exampel "= ?") for the first argument of sql.Exec()
func (db DB) OperatorAndPlaceholderOfValueForSQL(valueI interface{}, placeholderCounter int) string {
	switch valueI.(type) {
	case []int, []string, []float32, []float64, []int64:
		return " IN ("+db.Dialect.Placeholder(placeholderCounter)+")"
	case int, string, float32, float64, int64:
		return " = "+db.Dialect.Placeholder(placeholderCounter)
	case nil:
		return " IS NULL"
	default:
		return " = "+db.Dialect.Placeholder(placeholderCounter)
	}
}

// ValueForSQL generates the value argument for sql.Exec() [not-the-first arguments]
func (db DB) ValueForSQL(valueI interface{}) interface{} {
	switch value := valueI.(type) {
	case []int, []string, []float32, []float64, []int64:
		return `"`+strings.Replace(strings.Trim(fmt.Sprintf("%v", value), "[]"), ` `, `", "`, -1)+`"`
	case int, string, float32, float64, int64:
		return value
	case nil:
		return nil
	default:
		stringer, ok := value.(Stringer)
		if !ok {
			return fmt.Sprintf("%v", value)
		} else {
			return stringer.String()
		}
	}
}

// check interface
var _ DBTX = (*DB)(nil)
<|endoftext|>


<commit_before>/*
   Copyright 2014 CoreOS, Inc.

   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 raft

import (
	"fmt"
	"log"

	pb "github.com/coreos/etcd/raft/raftpb"
)

type raftLog struct {
	// storage contains all stable entries since the last snapshot.
	storage Storage
	// unstableEnts contains all entries that have not yet been written
	// to storage.
	unstableEnts []pb.Entry
	// unstableEnts[i] has raft log position i+unstable.  Note that
	// unstable may be less than the highest log position in storage;
	// this means that the next write to storage will truncate the log
	// before persisting unstableEnts.
	unstable uint64
	// committed is the highest log position that is known to be in
	// stable storage on a quorum of nodes.
	// Invariant: committed < unstable
	committed uint64
	// applied is the highest log position that the application has
	// been instructed to apply to its state machine.
	// Invariant: applied <= committed
	applied uint64
}

func newLog(storage Storage) *raftLog {
	if storage == nil {
		log.Panic("storage must not be nil")
	}
	log := &raftLog{
		storage: storage,
	}
	firstIndex, err := storage.FirstIndex()
	if err != nil {
		panic(err) // TODO(bdarnell)
	}
	lastIndex, err := storage.LastIndex()
	if err != nil {
		panic(err) // TODO(bdarnell)
	}
	log.unstable = lastIndex + 1
	// Initialize our committed and applied pointers to the time of the last compaction.
	log.committed = firstIndex - 1
	log.applied = firstIndex - 1

	return log
}

func (l *raftLog) String() string {
	return fmt.Sprintf("unstable=%d committed=%d applied=%d", l.unstable, l.committed, l.applied)
}

// maybeAppend returns (0, false) if the entries cannot be appended. Otherwise,
// it returns (last index of new entries, true).
func (l *raftLog) maybeAppend(index, logTerm, committed uint64, ents ...pb.Entry) (lastnewi uint64, ok bool) {
	lastnewi = index + uint64(len(ents))
	if l.matchTerm(index, logTerm) {
		from := index + 1
		ci := l.findConflict(from, ents)
		switch {
		case ci == 0:
		case ci <= l.committed:
			panic("conflict with committed entry")
		default:
			l.append(ci-1, ents[ci-from:]...)
		}
		l.commitTo(min(committed, lastnewi))
		return lastnewi, true
	}
	return 0, false
}

func (l *raftLog) append(after uint64, ents ...pb.Entry) uint64 {
	if after < l.committed {
		log.Panicf("after(%d) out of range [committed(%d)]", after, l.committed)
	}
	if after < l.unstable {
		// The log is being truncated to before our current unstable
		// portion, so discard it and reset unstable.
		l.unstableEnts = nil
		l.unstable = after + 1
	}
	// Truncate any unstable entries that are being replaced, then
	// append the new ones.
	l.unstableEnts = append(l.unstableEnts[0:1+after-l.unstable], ents...)
	l.unstable = min(l.unstable, after+1)
	return l.lastIndex()
}

// findConflict finds the index of the conflict.
// It returns the first pair of conflicting entries between the existing
// entries and the given entries, if there are any.
// If there is no conflicting entries, and the existing entries contains
// all the given entries, zero will be returned.
// If there is no conflicting entries, but the given entries contains new
// entries, the index of the first new entry will be returned.
// An entry is considered to be conflicting if it has the same index but
// a different term.
// The first entry MUST have an index equal to the argument 'from'.
// The index of the given entries MUST be continuously increasing.
func (l *raftLog) findConflict(from uint64, ents []pb.Entry) uint64 {
	// TODO(xiangli): validate the index of ents
	for i, ne := range ents {
		if oe := l.at(from + uint64(i)); oe == nil || oe.Term != ne.Term {
			return from + uint64(i)
		}
	}
	return 0
}

func (l *raftLog) unstableEntries() []pb.Entry {
	if len(l.unstableEnts) == 0 {
		return nil
	}
	return append([]pb.Entry{}, l.unstableEnts...)
}

// nextEnts returns all the available entries for execution.
// If applied is smaller than the index of snapshot, it returns all committed
// entries after the index of snapshot.
func (l *raftLog) nextEnts() (ents []pb.Entry) {
	off := max(l.applied+1, l.firstIndex())
	if l.committed+1 > off {
		return l.slice(off, l.committed+1)
	}
	return nil
}

func (l *raftLog) firstIndex() uint64 {
	index, err := l.storage.FirstIndex()
	if err != nil {
		panic(err) // TODO(bdarnell)
	}
	return index
}

func (l *raftLog) lastIndex() uint64 {
	if len(l.unstableEnts) > 0 {
		return l.unstable + uint64(len(l.unstableEnts)) - 1
	}
	index, err := l.storage.LastIndex()
	if err != nil {
		panic(err) // TODO(bdarnell)
	}
	return index
}

func (l *raftLog) commitTo(tocommit uint64) {
	// never decrease commit
	if l.committed < tocommit {
		if l.lastIndex() < tocommit {
			log.Panicf("tocommit(%d) is out of range [lastIndex(%d)]", tocommit, l.lastIndex())
		}
		l.committed = tocommit
	}
}

func (l *raftLog) appliedTo(i uint64) {
	if i == 0 {
		return
	}
	if l.committed < i || i < l.applied {
		log.Panicf("applied(%d) is out of range [prevApplied(%d), committed(%d)]", i, l.applied, l.committed)
	}
	l.applied = i
}

func (l *raftLog) stableTo(i uint64) {
	if i < l.unstable || i+1-l.unstable > uint64(len(l.unstableEnts)) {
		log.Panicf("stableTo(%d) is out of range [unstable(%d), len(unstableEnts)(%d)]",
			i, l.unstable, len(l.unstableEnts))
	}
	l.unstableEnts = l.unstableEnts[i+1-l.unstable:]
	l.unstable = i + 1
}

func (l *raftLog) lastTerm() uint64 {
	return l.term(l.lastIndex())
}

func (l *raftLog) term(i uint64) uint64 {
	if i < l.unstable {
		t, err := l.storage.Term(i)
		if err == ErrCompacted {
			return 0
		} else if err != nil {
			panic(err) // TODO(bdarnell)
		}
		return t
	}
	if i >= l.unstable+uint64(len(l.unstableEnts)) {
		return 0
	}
	return l.unstableEnts[i-l.unstable].Term
}

func (l *raftLog) entries(i uint64) []pb.Entry {
	return l.slice(i, l.lastIndex()+1)
}

// allEntries returns all entries in the log.
func (l *raftLog) allEntries() []pb.Entry {
	return l.entries(l.firstIndex())
}

// isUpToDate determines if the given (lastIndex,term) log is more up-to-date
// by comparing the index and term of the last entries in the existing logs.
// If the logs have last entries with different terms, then the log with the
// later term is more up-to-date. If the logs end with the same term, then
// whichever log has the larger lastIndex is more up-to-date. If the logs are
// the same, the given log is up-to-date.
func (l *raftLog) isUpToDate(lasti, term uint64) bool {
	return term > l.lastTerm() || (term == l.lastTerm() && lasti >= l.lastIndex())
}

func (l *raftLog) matchTerm(i, term uint64) bool {
	return l.term(i) == term
}

func (l *raftLog) maybeCommit(maxIndex, term uint64) bool {
	if maxIndex > l.committed && l.term(maxIndex) == term {
		l.commitTo(maxIndex)
		return true
	}
	return false
}

func (l *raftLog) restore(s pb.Snapshot) {
	err := l.storage.ApplySnapshot(s)
	if err != nil {
		panic(err) // TODO(bdarnell)
	}
	l.committed = s.Metadata.Index
	l.applied = s.Metadata.Index
	l.unstable = l.committed + 1
	l.unstableEnts = nil
}

func (l *raftLog) at(i uint64) *pb.Entry {
	ents := l.slice(i, i+1)
	if len(ents) == 0 {
		return nil
	}
	return &ents[0]
}

// slice returns a slice of log entries from lo through hi-1, inclusive.
func (l *raftLog) slice(lo uint64, hi uint64) []pb.Entry {
	if lo >= hi {
		return nil
	}
	if l.isOutOfBounds(lo) || l.isOutOfBounds(hi-1) {
		return nil
	}
	var ents []pb.Entry
	if lo < l.unstable {
		storedEnts, err := l.storage.Entries(lo, min(hi, l.unstable))
		if err == ErrCompacted {
			return nil
		} else if err != nil {
			panic(err) // TODO(bdarnell)
		}
		ents = append(ents, storedEnts...)
	}
	if len(l.unstableEnts) > 0 && hi > l.unstable {
		firstUnstable := max(lo, l.unstable)
		ents = append(ents, l.unstableEnts[firstUnstable-l.unstable:hi-l.unstable]...)
	}
	return ents
}

func (l *raftLog) isOutOfBounds(i uint64) bool {
	if i < l.firstIndex() || i > l.lastIndex() {
		return true
	}
	return false
}

func (l *raftLog) isOutOfAppliedBounds(i uint64) bool {
	if i < l.firstIndex() || i > l.applied {
		return true
	}
	return false
}

func min(a, b uint64) uint64 {
	if a > b {
		return b
	}
	return a
}

func max(a, b uint64) uint64 {
	if a > b {
		return a
	}
	return b
}
<commit_msg>raft: add comment for append in unstableEntries in log.go<commit_after>/*
   Copyright 2014 CoreOS, Inc.

   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 raft

import (
	"fmt"
	"log"

	pb "github.com/coreos/etcd/raft/raftpb"
)

type raftLog struct {
	// storage contains all stable entries since the last snapshot.
	storage Storage
	// unstableEnts contains all entries that have not yet been written
	// to storage.
	unstableEnts []pb.Entry
	// unstableEnts[i] has raft log position i+unstable.  Note that
	// unstable may be less than the highest log position in storage;
	// this means that the next write to storage will truncate the log
	// before persisting unstableEnts.
	unstable uint64
	// committed is the highest log position that is known to be in
	// stable storage on a quorum of nodes.
	// Invariant: committed < unstable
	committed uint64
	// applied is the highest log position that the application has
	// been instructed to apply to its state machine.
	// Invariant: applied <= committed
	applied uint64
}

func newLog(storage Storage) *raftLog {
	if storage == nil {
		log.Panic("storage must not be nil")
	}
	log := &raftLog{
		storage: storage,
	}
	firstIndex, err := storage.FirstIndex()
	if err != nil {
		panic(err) // TODO(bdarnell)
	}
	lastIndex, err := storage.LastIndex()
	if err != nil {
		panic(err) // TODO(bdarnell)
	}
	log.unstable = lastIndex + 1
	// Initialize our committed and applied pointers to the time of the last compaction.
	log.committed = firstIndex - 1
	log.applied = firstIndex - 1

	return log
}

func (l *raftLog) String() string {
	return fmt.Sprintf("unstable=%d committed=%d applied=%d", l.unstable, l.committed, l.applied)
}

// maybeAppend returns (0, false) if the entries cannot be appended. Otherwise,
// it returns (last index of new entries, true).
func (l *raftLog) maybeAppend(index, logTerm, committed uint64, ents ...pb.Entry) (lastnewi uint64, ok bool) {
	lastnewi = index + uint64(len(ents))
	if l.matchTerm(index, logTerm) {
		from := index + 1
		ci := l.findConflict(from, ents)
		switch {
		case ci == 0:
		case ci <= l.committed:
			panic("conflict with committed entry")
		default:
			l.append(ci-1, ents[ci-from:]...)
		}
		l.commitTo(min(committed, lastnewi))
		return lastnewi, true
	}
	return 0, false
}

func (l *raftLog) append(after uint64, ents ...pb.Entry) uint64 {
	if after < l.committed {
		log.Panicf("after(%d) out of range [committed(%d)]", after, l.committed)
	}
	if after < l.unstable {
		// The log is being truncated to before our current unstable
		// portion, so discard it and reset unstable.
		l.unstableEnts = nil
		l.unstable = after + 1
	}
	// Truncate any unstable entries that are being replaced, then
	// append the new ones.
	l.unstableEnts = append(l.unstableEnts[0:1+after-l.unstable], ents...)
	l.unstable = min(l.unstable, after+1)
	return l.lastIndex()
}

// findConflict finds the index of the conflict.
// It returns the first pair of conflicting entries between the existing
// entries and the given entries, if there are any.
// If there is no conflicting entries, and the existing entries contains
// all the given entries, zero will be returned.
// If there is no conflicting entries, but the given entries contains new
// entries, the index of the first new entry will be returned.
// An entry is considered to be conflicting if it has the same index but
// a different term.
// The first entry MUST have an index equal to the argument 'from'.
// The index of the given entries MUST be continuously increasing.
func (l *raftLog) findConflict(from uint64, ents []pb.Entry) uint64 {
	// TODO(xiangli): validate the index of ents
	for i, ne := range ents {
		if oe := l.at(from + uint64(i)); oe == nil || oe.Term != ne.Term {
			return from + uint64(i)
		}
	}
	return 0
}

func (l *raftLog) unstableEntries() []pb.Entry {
	if len(l.unstableEnts) == 0 {
		return nil
	}
	// copy unstable entries to an empty slice
	return append([]pb.Entry{}, l.unstableEnts...)
}

// nextEnts returns all the available entries for execution.
// If applied is smaller than the index of snapshot, it returns all committed
// entries after the index of snapshot.
func (l *raftLog) nextEnts() (ents []pb.Entry) {
	off := max(l.applied+1, l.firstIndex())
	if l.committed+1 > off {
		return l.slice(off, l.committed+1)
	}
	return nil
}

func (l *raftLog) firstIndex() uint64 {
	index, err := l.storage.FirstIndex()
	if err != nil {
		panic(err) // TODO(bdarnell)
	}
	return index
}

func (l *raftLog) lastIndex() uint64 {
	if len(l.unstableEnts) > 0 {
		return l.unstable + uint64(len(l.unstableEnts)) - 1
	}
	index, err := l.storage.LastIndex()
	if err != nil {
		panic(err) // TODO(bdarnell)
	}
	return index
}

func (l *raftLog) commitTo(tocommit uint64) {
	// never decrease commit
	if l.committed < tocommit {
		if l.lastIndex() < tocommit {
			log.Panicf("tocommit(%d) is out of range [lastIndex(%d)]", tocommit, l.lastIndex())
		}
		l.committed = tocommit
	}
}

func (l *raftLog) appliedTo(i uint64) {
	if i == 0 {
		return
	}
	if l.committed < i || i < l.applied {
		log.Panicf("applied(%d) is out of range [prevApplied(%d), committed(%d)]", i, l.applied, l.committed)
	}
	l.applied = i
}

func (l *raftLog) stableTo(i uint64) {
	if i < l.unstable || i+1-l.unstable > uint64(len(l.unstableEnts)) {
		log.Panicf("stableTo(%d) is out of range [unstable(%d), len(unstableEnts)(%d)]",
			i, l.unstable, len(l.unstableEnts))
	}
	l.unstableEnts = l.unstableEnts[i+1-l.unstable:]
	l.unstable = i + 1
}

func (l *raftLog) lastTerm() uint64 {
	return l.term(l.lastIndex())
}

func (l *raftLog) term(i uint64) uint64 {
	if i < l.unstable {
		t, err := l.storage.Term(i)
		if err == ErrCompacted {
			return 0
		} else if err != nil {
			panic(err) // TODO(bdarnell)
		}
		return t
	}
	if i >= l.unstable+uint64(len(l.unstableEnts)) {
		return 0
	}
	return l.unstableEnts[i-l.unstable].Term
}

func (l *raftLog) entries(i uint64) []pb.Entry {
	return l.slice(i, l.lastIndex()+1)
}

// allEntries returns all entries in the log.
func (l *raftLog) allEntries() []pb.Entry {
	return l.entries(l.firstIndex())
}

// isUpToDate determines if the given (lastIndex,term) log is more up-to-date
// by comparing the index and term of the last entries in the existing logs.
// If the logs have last entries with different terms, then the log with the
// later term is more up-to-date. If the logs end with the same term, then
// whichever log has the larger lastIndex is more up-to-date. If the logs are
// the same, the given log is up-to-date.
func (l *raftLog) isUpToDate(lasti, term uint64) bool {
	return term > l.lastTerm() || (term == l.lastTerm() && lasti >= l.lastIndex())
}

func (l *raftLog) matchTerm(i, term uint64) bool {
	return l.term(i) == term
}

func (l *raftLog) maybeCommit(maxIndex, term uint64) bool {
	if maxIndex > l.committed && l.term(maxIndex) == term {
		l.commitTo(maxIndex)
		return true
	}
	return false
}

func (l *raftLog) restore(s pb.Snapshot) {
	err := l.storage.ApplySnapshot(s)
	if err != nil {
		panic(err) // TODO(bdarnell)
	}
	l.committed = s.Metadata.Index
	l.applied = s.Metadata.Index
	l.unstable = l.committed + 1
	l.unstableEnts = nil
}

func (l *raftLog) at(i uint64) *pb.Entry {
	ents := l.slice(i, i+1)
	if len(ents) == 0 {
		return nil
	}
	return &ents[0]
}

// slice returns a slice of log entries from lo through hi-1, inclusive.
func (l *raftLog) slice(lo uint64, hi uint64) []pb.Entry {
	if lo >= hi {
		return nil
	}
	if l.isOutOfBounds(lo) || l.isOutOfBounds(hi-1) {
		return nil
	}
	var ents []pb.Entry
	if lo < l.unstable {
		storedEnts, err := l.storage.Entries(lo, min(hi, l.unstable))
		if err == ErrCompacted {
			return nil
		} else if err != nil {
			panic(err) // TODO(bdarnell)
		}
		ents = append(ents, storedEnts...)
	}
	if len(l.unstableEnts) > 0 && hi > l.unstable {
		firstUnstable := max(lo, l.unstable)
		ents = append(ents, l.unstableEnts[firstUnstable-l.unstable:hi-l.unstable]...)
	}
	return ents
}

func (l *raftLog) isOutOfBounds(i uint64) bool {
	if i < l.firstIndex() || i > l.lastIndex() {
		return true
	}
	return false
}

func (l *raftLog) isOutOfAppliedBounds(i uint64) bool {
	if i < l.firstIndex() || i > l.applied {
		return true
	}
	return false
}

func min(a, b uint64) uint64 {
	if a > b {
		return b
	}
	return a
}

func max(a, b uint64) uint64 {
	if a > b {
		return a
	}
	return b
}
<|endoftext|>


<commit_before>package sudoku

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

type CellList []*Cell

type IntSlice []int

type stringSlice []string

func getRow(cell *Cell) int {
	return cell.Row
}

func getCol(cell *Cell) int {
	return cell.Col
}

func getBlock(cell *Cell) int {
	return cell.Block
}

func (self CellList) SameRow() bool {
	return self.CollectNums(getRow).Same()
}

func (self CellList) SameCol() bool {
	return self.CollectNums(getCol).Same()
}

func (self CellList) SameBlock() bool {
	return self.CollectNums(getBlock).Same()
}

func (self CellList) Row() int {
	//Will return the row of a random item.
	if len(self) == 0 {
		return 0
	}
	return self[0].Row
}

func (self CellList) Col() int {
	if len(self) == 0 {
		return 0
	}
	return self[0].Col
}

func (self CellList) Block() int {
	if len(self) == 0 {
		return 0
	}
	return self[0].Block
}

func (self CellList) AddExclude(exclude int) {
	mapper := func(cell *Cell) {
		cell.setExcluded(exclude, true)
	}
	self.Map(mapper)
}

func (self CellList) FilterByPossible(possible int) CellList {
	//TODO: test this
	filter := func(cell *Cell) bool {
		return cell.Possible(possible)
	}
	return self.Filter(filter)
}

func (self CellList) FilterByNumPossibilities(target int) CellList {
	//TODO: test this
	filter := func(cell *Cell) bool {
		return len(cell.Possibilities()) == target
	}
	return self.Filter(filter)
}

func (self CellList) FilterByHasPossibilities() CellList {
	//Returns a list of cells that have possibilities.
	//TODO: test this.
	filter := func(cell *Cell) bool {
		return len(cell.Possibilities()) > 0
	}
	return self.Filter(filter)
}

func (self CellList) RemoveCells(targets CellList) CellList {
	//TODO: test this.
	targetCells := make(map[*Cell]bool)
	for _, cell := range targets {
		targetCells[cell] = true
	}
	filterFunc := func(cell *Cell) bool {
		return !targetCells[cell]
	}
	return self.Filter(filterFunc)
}

func (self CellList) PossibilitiesUnion() IntSlice {
	//Returns an IntSlice of the union of all possibilities.
	set := make(map[int]bool)

	for _, cell := range self {
		for _, possibility := range cell.Possibilities() {
			set[possibility] = true
		}
	}

	result := make(IntSlice, len(set))

	i := 0
	for possibility, _ := range set {
		result[i] = possibility
		i++
	}

	return result
}

func (self CellList) Subset(indexes IntSlice) CellList {
	//TODO: what's this behavior if indexes has dupes? What SHOULD it be?
	result := make(CellList, len(indexes))
	max := len(self)
	for i, index := range indexes {
		if index >= max {
			//This probably is indicative of a larger problem.
			continue
		}
		result[i] = self[index]
	}
	return result
}

func (self CellList) InverseSubset(indexes IntSlice) CellList {
	//TODO: figure out what this should do when presented with dupes.

	//LIke Subset, but returns all of the items NOT called out in indexes.
	var result CellList

	//Ensure indexes are in sorted order.
	sort.Ints(indexes)

	//Index into indexes we're considering
	currentIndex := 0

	for i := 0; i < len(self); i++ {
		if currentIndex < len(indexes) && i == indexes[currentIndex] {
			//Skip it!
			currentIndex++
		} else {
			//Output it!
			result = append(result, self[i])
		}
	}

	return result
}

func (self CellList) CollectNums(fetcher func(*Cell) int) IntSlice {
	var result IntSlice
	for _, cell := range self {
		result = append(result, fetcher(cell))
	}
	return result
}

func (self CellList) Filter(filter func(*Cell) bool) CellList {
	var result CellList
	for _, cell := range self {
		if filter(cell) {
			result = append(result, cell)
		}
	}
	return result
}

func (self CellList) Map(mapper func(*Cell)) {
	for _, cell := range self {
		mapper(cell)
	}
}

func (self CellList) Description() string {
	strings := make(stringSlice, len(self))

	for i, cell := range self {
		strings[i] = fmt.Sprintf("(%d,%d)", cell.Row, cell.Col)
	}

	return strings.description()
}

func (self stringSlice) description() string {
	if len(self) == 0 {
		return ""
	}

	if len(self) == 1 {
		return self[0]
	}

	if len(self) == 2 {
		return self[0] + " and " + self[1]
	}

	result := strings.Join(self[:len(self)-1], ", ")

	return result + ", and " + self[len(self)-1]
}

func (self IntSlice) Description() string {

	strings := make(stringSlice, len(self))

	for i, num := range self {
		strings[i] = strconv.Itoa(num)
	}

	return strings.description()

}

func (self IntSlice) Same() bool {
	if len(self) == 0 {
		return true
	}
	target := self[0]
	for _, num := range self {
		if target != num {
			return false
		}
	}
	return true
}

func (self IntSlice) SameContentAs(otherSlice IntSlice) bool {
	//Same as SameAs, but doesn't care about order.

	selfToUse := make(IntSlice, len(self))
	copy(selfToUse, self)
	sort.IntSlice(selfToUse).Sort()

	otherToUse := make(IntSlice, len(otherSlice))
	copy(otherToUse, otherSlice)
	sort.IntSlice(otherToUse).Sort()

	return selfToUse.SameAs(otherToUse)
}

func (self IntSlice) SameAs(other IntSlice) bool {
	//TODO: test this.
	if len(self) != len(other) {
		return false
	}
	for i, num := range self {
		if other[i] != num {
			return false
		}
	}
	return true
}
<commit_msg>Define IntSlice.Subset (just same impl copied from CellList)<commit_after>package sudoku

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

type CellList []*Cell

type IntSlice []int

type stringSlice []string

func getRow(cell *Cell) int {
	return cell.Row
}

func getCol(cell *Cell) int {
	return cell.Col
}

func getBlock(cell *Cell) int {
	return cell.Block
}

func (self CellList) SameRow() bool {
	return self.CollectNums(getRow).Same()
}

func (self CellList) SameCol() bool {
	return self.CollectNums(getCol).Same()
}

func (self CellList) SameBlock() bool {
	return self.CollectNums(getBlock).Same()
}

func (self CellList) Row() int {
	//Will return the row of a random item.
	if len(self) == 0 {
		return 0
	}
	return self[0].Row
}

func (self CellList) Col() int {
	if len(self) == 0 {
		return 0
	}
	return self[0].Col
}

func (self CellList) Block() int {
	if len(self) == 0 {
		return 0
	}
	return self[0].Block
}

func (self CellList) AddExclude(exclude int) {
	mapper := func(cell *Cell) {
		cell.setExcluded(exclude, true)
	}
	self.Map(mapper)
}

func (self CellList) FilterByPossible(possible int) CellList {
	//TODO: test this
	filter := func(cell *Cell) bool {
		return cell.Possible(possible)
	}
	return self.Filter(filter)
}

func (self CellList) FilterByNumPossibilities(target int) CellList {
	//TODO: test this
	filter := func(cell *Cell) bool {
		return len(cell.Possibilities()) == target
	}
	return self.Filter(filter)
}

func (self CellList) FilterByHasPossibilities() CellList {
	//Returns a list of cells that have possibilities.
	//TODO: test this.
	filter := func(cell *Cell) bool {
		return len(cell.Possibilities()) > 0
	}
	return self.Filter(filter)
}

func (self CellList) RemoveCells(targets CellList) CellList {
	//TODO: test this.
	targetCells := make(map[*Cell]bool)
	for _, cell := range targets {
		targetCells[cell] = true
	}
	filterFunc := func(cell *Cell) bool {
		return !targetCells[cell]
	}
	return self.Filter(filterFunc)
}

func (self CellList) PossibilitiesUnion() IntSlice {
	//Returns an IntSlice of the union of all possibilities.
	set := make(map[int]bool)

	for _, cell := range self {
		for _, possibility := range cell.Possibilities() {
			set[possibility] = true
		}
	}

	result := make(IntSlice, len(set))

	i := 0
	for possibility, _ := range set {
		result[i] = possibility
		i++
	}

	return result
}

func (self CellList) Subset(indexes IntSlice) CellList {
	//IntSlice.Subset is basically a carbon copy.
	//TODO: what's this behavior if indexes has dupes? What SHOULD it be?
	result := make(CellList, len(indexes))
	max := len(self)
	for i, index := range indexes {
		if index >= max {
			//This probably is indicative of a larger problem.
			continue
		}
		result[i] = self[index]
	}
	return result
}

func (self CellList) InverseSubset(indexes IntSlice) CellList {
	//TODO: figure out what this should do when presented with dupes.

	//LIke Subset, but returns all of the items NOT called out in indexes.
	var result CellList

	//Ensure indexes are in sorted order.
	sort.Ints(indexes)

	//Index into indexes we're considering
	currentIndex := 0

	for i := 0; i < len(self); i++ {
		if currentIndex < len(indexes) && i == indexes[currentIndex] {
			//Skip it!
			currentIndex++
		} else {
			//Output it!
			result = append(result, self[i])
		}
	}

	return result
}

func (self CellList) CollectNums(fetcher func(*Cell) int) IntSlice {
	var result IntSlice
	for _, cell := range self {
		result = append(result, fetcher(cell))
	}
	return result
}

func (self CellList) Filter(filter func(*Cell) bool) CellList {
	var result CellList
	for _, cell := range self {
		if filter(cell) {
			result = append(result, cell)
		}
	}
	return result
}

func (self CellList) Map(mapper func(*Cell)) {
	for _, cell := range self {
		mapper(cell)
	}
}

func (self CellList) Description() string {
	strings := make(stringSlice, len(self))

	for i, cell := range self {
		strings[i] = fmt.Sprintf("(%d,%d)", cell.Row, cell.Col)
	}

	return strings.description()
}

func (self stringSlice) description() string {
	if len(self) == 0 {
		return ""
	}

	if len(self) == 1 {
		return self[0]
	}

	if len(self) == 2 {
		return self[0] + " and " + self[1]
	}

	result := strings.Join(self[:len(self)-1], ", ")

	return result + ", and " + self[len(self)-1]
}

func (self IntSlice) Description() string {

	strings := make(stringSlice, len(self))

	for i, num := range self {
		strings[i] = strconv.Itoa(num)
	}

	return strings.description()

}

func (self IntSlice) Same() bool {
	if len(self) == 0 {
		return true
	}
	target := self[0]
	for _, num := range self {
		if target != num {
			return false
		}
	}
	return true
}

func (self IntSlice) SameContentAs(otherSlice IntSlice) bool {
	//Same as SameAs, but doesn't care about order.

	selfToUse := make(IntSlice, len(self))
	copy(selfToUse, self)
	sort.IntSlice(selfToUse).Sort()

	otherToUse := make(IntSlice, len(otherSlice))
	copy(otherToUse, otherSlice)
	sort.IntSlice(otherToUse).Sort()

	return selfToUse.SameAs(otherToUse)
}

func (self IntSlice) SameAs(other IntSlice) bool {
	//TODO: test this.
	if len(self) != len(other) {
		return false
	}
	for i, num := range self {
		if other[i] != num {
			return false
		}
	}
	return true
}

func (self IntSlice) Subset(indexes IntSlice) IntSlice {
	//TODO: test this.
	//Basically a carbon copy of CellList.Subset
	//TODO: what's this behavior if indexes has dupes? What SHOULD it be?
	result := make(IntSlice, len(indexes))
	max := len(self)
	for i, index := range indexes {
		if index >= max {
			//This probably is indicative of a larger problem.
			continue
		}
		result[i] = self[index]
	}
	return result
}
<|endoftext|>


<commit_before>package disk

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"io/ioutil"
	"os"
	"syscall"

	"code.google.com/p/go.crypto/nacl/secretbox"
	"code.google.com/p/go.crypto/scrypt"
	"code.google.com/p/goprotobuf/proto"
)

const (
	kdfSaltLen    = 32
	kdfKeyLen     = 32
	erasureKeyLen = 32
)

var headerMagic = [8]byte{0xa8, 0x34, 0x64, 0x9e, 0xce, 0x39, 0x94, 0xe3}

// ErasureStorage represents a type of storage that can store, and erase, small
// amounts of data.
type ErasureStorage interface {
	// Create creates a new erasure storage object and fills out header to
	// include the needed values.
	Create(header *Header, key *[kdfKeyLen]byte) error
	// Read reads the current value of the storage.
	Read(key *[kdfKeyLen]byte) (*[erasureKeyLen]byte, error)
	// Write requests that the given value be stored and the old value
	// forgotten.
	Write(key *[kdfKeyLen]byte, value *[erasureKeyLen]byte) error
}

// erasureRegistry is a slice of functions, each of which can inspect a header
// and optionally return an ErasureStorage that loads the mask key specified by
// that header.
var erasureRegistry []func(*Header) ErasureStorage

// StateFile encapsulates information about a state file on diskl
type StateFile struct {
	Path string
	Rand io.Reader
	Log  func(format string, args ...interface{})
	// Erasure is able to store a `mask key' - a random value that is XORed
	// with the key. This is done because an ErasureStorage is believed to
	// be able to erase old mask values.
	Erasure ErasureStorage

	header Header
	key    [kdfKeyLen]byte
	mask   [erasureKeyLen]byte
	valid  bool
}

func NewStateFile(rand io.Reader, path string) *StateFile {
	return &StateFile{
		Rand: rand,
		Path: path,
	}
}

func (sf *StateFile) Lock(create bool) (*Lock, error) {
	flags := os.O_RDWR
	if create {
		flags |= os.O_CREATE | os.O_EXCL
	}
	file, err := os.OpenFile(sf.Path, flags, 0600)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	fd := int(file.Fd())
	newFd, err := syscall.Dup(fd)
	if err != nil {
		return nil, err
	}
	if syscall.Flock(newFd, syscall.LOCK_EX|syscall.LOCK_NB) != nil {
		syscall.Close(newFd)
		return nil, nil
	}
	return &Lock{newFd}, nil
}

func (sf *StateFile) deriveKey(pw string) error {
	if len(pw) == 0 && sf.header.Scrypt != nil {
		return BadPasswordError
	}
	params := sf.header.Scrypt
	key, err := scrypt.Key([]byte(pw), sf.header.KdfSalt, int(params.GetN()), int(params.GetR()), int(params.GetP()), kdfKeyLen)
	if err != nil {
		return err
	}
	copy(sf.key[:], key)
	return nil
}

func (sf *StateFile) Create(pw string) error {
	var salt [kdfSaltLen]byte
	if _, err := io.ReadFull(sf.Rand, salt[:]); err != nil {
		return err
	}

	if len(pw) > 0 {
		sf.header.KdfSalt = salt[:]
		if err := sf.deriveKey(pw); err != nil {
			return err
		}
		sf.header.Scrypt = new(Header_SCrypt)
	}

	if sf.Erasure != nil {
		if err := sf.Erasure.Create(&sf.header, &sf.key); err != nil {
			return err
		}
		if _, err := io.ReadFull(sf.Rand, sf.mask[:]); err != nil {
			return err
		}
		if err := sf.Erasure.Write(&sf.key, &sf.mask); err != nil {
			return err
		}
	} else {
		sf.header.NoErasureStorage = proto.Bool(true)
	}

	sf.valid = true
	return nil
}

func (sf *StateFile) Read(pw string) (*State, error) {
	b, err := ioutil.ReadFile(sf.Path)
	if err != nil {
		return nil, err
	}

	if len(b) < len(headerMagic)+4 {
		return nil, errors.New("state file is too small to be valid")
	}

	if !bytes.Equal(b[:len(headerMagic)], headerMagic[:]) {
		sf.header.NoErasureStorage = proto.Bool(true)
		if len(pw) > 0 {
			sf.header.Scrypt = new(Header_SCrypt)
			sf.header.KdfSalt = b[:32]
			if err := sf.deriveKey(pw); err != nil {
				return nil, err
			}
		}
		b = b[32:]
		state, err := sf.readOldStyle(b)
		if err != nil {
			return nil, err
		}
		return state, nil
	}

	b = b[len(headerMagic):]
	headerLen := binary.LittleEndian.Uint32(b)
	b = b[4:]
	if headerLen > 1<<16 {
		return nil, errors.New("state file corrupt")
	}
	if len(b) < int(headerLen) {
		return nil, errors.New("state file truncated")
	}
	headerBytes := b[:int(headerLen)]
	b = b[int(headerLen):]

	if err := proto.Unmarshal(headerBytes, &sf.header); err != nil {
		return nil, err
	}
	if len(pw) > 0 {
		if err := sf.deriveKey(pw); err != nil {
			return nil, err
		}
	}

	if !sf.header.GetNoErasureStorage() {
		for _, erasureMethod := range erasureRegistry {
			sf.Erasure = erasureMethod(&sf.header)
			if sf.Erasure != nil {
				break
			}
		}
		if sf.Erasure == nil {
			return nil, errors.New("unknown erasure storage method")
		}

		mask, err := sf.Erasure.Read(&sf.key)
		if err != nil {
			return nil, err
		}
		copy(sf.mask[:], mask[:])
	}

	smearedCopies := int(sf.header.GetNonceSmearCopies())

	if len(b) < 24*smearedCopies {
		return nil, errors.New("state file truncated")
	}

	var nonce [24]byte
	for i := 0; i < smearedCopies; i++ {
		for j := 0; j < 24; j++ {
			nonce[j] ^= b[24*i+j]
		}
	}

	b = b[24*smearedCopies:]

	var effectiveKey [kdfKeyLen]byte
	for i := range effectiveKey {
		effectiveKey[i] = sf.mask[i] ^ sf.key[i]
	}
	plaintext, ok := secretbox.Open(nil, b, &nonce, &effectiveKey)
	if !ok {
		return nil, BadPasswordError
	}
	if len(plaintext) < 4 {
		return nil, errors.New("state file corrupt")
	}
	length := binary.LittleEndian.Uint32(plaintext[:4])
	plaintext = plaintext[4:]
	if length > 1<<31 || length > uint32(len(plaintext)) {
		return nil, errors.New("state file corrupt")
	}
	plaintext = plaintext[:int(length)]

	var state State
	if err := proto.Unmarshal(plaintext, &state); err != nil {
		return nil, err
	}

	return &state, nil
}

func (sf *StateFile) readOldStyle(b []byte) (*State, error) {
	return loadOldState(b, &sf.key)
}

type NewState struct {
	State                []byte
	RotateErasureStorage bool
}

func (sf *StateFile) StartWriter(states chan NewState, done chan struct{}) {
	for {
		newState, ok := <-states
		if !ok {
			close(done)
			return
		}

		s := newState.State

		length := uint32(len(s)) + 4
		for i := uint(17); i < 32; i++ {
			if n := (uint32(1) << i); n >= length {
				length = n
				break
			}
		}

		plaintext := make([]byte, length)
		copy(plaintext[4:], s)
		if _, err := io.ReadFull(sf.Rand, plaintext[len(s)+4:]); err != nil {
			panic(err)
		}
		binary.LittleEndian.PutUint32(plaintext, uint32(len(s)))

		smearCopies := int(sf.header.GetNonceSmearCopies())
		nonceSmear := make([]byte, 24*smearCopies)
		if _, err := io.ReadFull(sf.Rand, nonceSmear[:]); err != nil {
			panic(err)
		}

		var nonce [24]byte
		for i := 0; i < smearCopies; i++ {
			for j := 0; j < 24; j++ {
				nonce[j] ^= nonceSmear[24*i+j]
			}
		}

		if sf.Erasure != nil && newState.RotateErasureStorage {
			var newMask [erasureKeyLen]byte
			if _, err := io.ReadFull(sf.Rand, newMask[:]); err != nil {
				panic(err)
			}
			if err := sf.Erasure.Write(&sf.key, &newMask); err != nil {
				sf.Log("Failed to write new erasure value: %s", err)
			} else {
				copy(sf.mask[:], newMask[:])
			}
		}

		var effectiveKey [kdfKeyLen]byte
		for i := range effectiveKey {
			effectiveKey[i] = sf.mask[i] ^ sf.key[i]
		}
		ciphertext := secretbox.Seal(nil, plaintext, &nonce, &effectiveKey)

		out, err := os.OpenFile(sf.Path, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0600)
		if err != nil {
			panic(err)
		}
		headerBytes, err := proto.Marshal(&sf.header)
		if err != nil {
			panic(err)
		}
		if _, err := out.Write(headerMagic[:]); err != nil {
			panic(err)
		}
		if err := binary.Write(out, binary.LittleEndian, uint32(len(headerBytes))); err != nil {
			panic(err)
		}
		if _, err := out.Write(headerBytes); err != nil {
			panic(err)
		}
		if _, err := out.Write(nonceSmear[:]); err != nil {
			panic(err)
		}
		if _, err := out.Write(ciphertext); err != nil {
			panic(err)
		}
		out.Close()
	}
}

type Lock struct {
	fd int
}

func (l *Lock) Close() {
	syscall.Flock(l.fd, syscall.LOCK_UN)
	syscall.Close(l.fd)
}

var BadPasswordError = errors.New("bad password")

func loadOldState(b []byte, key *[32]byte) (*State, error) {
	const (
		SCryptSaltLen = 32
		smearedCopies = 32768 / 24
	)

	if len(b) < SCryptSaltLen+24*smearedCopies {
		return nil, errors.New("state file is too small to be valid")
	}

	var nonce [24]byte
	for i := 0; i < smearedCopies; i++ {
		for j := 0; j < 24; j++ {
			nonce[j] ^= b[24*i+j]
		}
	}

	b = b[24*smearedCopies:]
	plaintext, ok := secretbox.Open(nil, b, &nonce, key)
	if !ok {
		return nil, BadPasswordError
	}
	if len(plaintext) < 4 {
		return nil, errors.New("state file corrupt")
	}
	length := binary.LittleEndian.Uint32(plaintext[:4])
	plaintext = plaintext[4:]
	if length > 1<<31 || length > uint32(len(plaintext)) {
		return nil, errors.New("state file corrupt")
	}
	plaintext = plaintext[:int(length)]

	var state State
	if err := proto.Unmarshal(plaintext, &state); err != nil {
		return nil, err
	}

	return &state, nil
}
<commit_msg>Added untested code to ensure that Pond statefile writes occur atomically; i.e., writes occur to a temporary file without truncating it. In the event that writing fails, Pond will leave behind the old statefile. Not yet tested.<commit_after>package disk

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"io/ioutil"
	"os"
	"syscall"

	"code.google.com/p/go.crypto/nacl/secretbox"
	"code.google.com/p/go.crypto/scrypt"
	"code.google.com/p/goprotobuf/proto"
)

const (
	kdfSaltLen    = 32
	kdfKeyLen     = 32
	erasureKeyLen = 32
)

var headerMagic = [8]byte{0xa8, 0x34, 0x64, 0x9e, 0xce, 0x39, 0x94, 0xe3}

// ErasureStorage represents a type of storage that can store, and erase, small
// amounts of data.
type ErasureStorage interface {
	// Create creates a new erasure storage object and fills out header to
	// include the needed values.
	Create(header *Header, key *[kdfKeyLen]byte) error
	// Read reads the current value of the storage.
	Read(key *[kdfKeyLen]byte) (*[erasureKeyLen]byte, error)
	// Write requests that the given value be stored and the old value
	// forgotten.
	Write(key *[kdfKeyLen]byte, value *[erasureKeyLen]byte) error
}

// erasureRegistry is a slice of functions, each of which can inspect a header
// and optionally return an ErasureStorage that loads the mask key specified by
// that header.
var erasureRegistry []func(*Header) ErasureStorage

// StateFile encapsulates information about a state file on diskl
type StateFile struct {
	Path string
	Rand io.Reader
	Log  func(format string, args ...interface{})
	// Erasure is able to store a `mask key' - a random value that is XORed
	// with the key. This is done because an ErasureStorage is believed to
	// be able to erase old mask values.
	Erasure ErasureStorage

	header Header
	key    [kdfKeyLen]byte
	mask   [erasureKeyLen]byte
	valid  bool
}

func NewStateFile(rand io.Reader, path string) *StateFile {
	return &StateFile{
		Rand: rand,
		Path: path,
	}
}

func (sf *StateFile) Lock(create bool) (*Lock, error) {
	flags := os.O_RDWR
	if create {
		flags |= os.O_CREATE | os.O_EXCL
	}
	file, err := os.OpenFile(sf.Path, flags, 0600)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	fd := int(file.Fd())
	newFd, err := syscall.Dup(fd)
	if err != nil {
		return nil, err
	}
	if syscall.Flock(newFd, syscall.LOCK_EX|syscall.LOCK_NB) != nil {
		syscall.Close(newFd)
		return nil, nil
	}
	return &Lock{newFd}, nil
}

func (sf *StateFile) deriveKey(pw string) error {
	if len(pw) == 0 && sf.header.Scrypt != nil {
		return BadPasswordError
	}
	params := sf.header.Scrypt
	key, err := scrypt.Key([]byte(pw), sf.header.KdfSalt, int(params.GetN()), int(params.GetR()), int(params.GetP()), kdfKeyLen)
	if err != nil {
		return err
	}
	copy(sf.key[:], key)
	return nil
}

func (sf *StateFile) Create(pw string) error {
	var salt [kdfSaltLen]byte
	if _, err := io.ReadFull(sf.Rand, salt[:]); err != nil {
		return err
	}

	if len(pw) > 0 {
		sf.header.KdfSalt = salt[:]
		if err := sf.deriveKey(pw); err != nil {
			return err
		}
		sf.header.Scrypt = new(Header_SCrypt)
	}

	if sf.Erasure != nil {
		if err := sf.Erasure.Create(&sf.header, &sf.key); err != nil {
			return err
		}
		if _, err := io.ReadFull(sf.Rand, sf.mask[:]); err != nil {
			return err
		}
		if err := sf.Erasure.Write(&sf.key, &sf.mask); err != nil {
			return err
		}
	} else {
		sf.header.NoErasureStorage = proto.Bool(true)
	}

	sf.valid = true
	return nil
}

func (sf *StateFile) Read(pw string) (*State, error) {
	b, err := ioutil.ReadFile(sf.Path)
	if err != nil {
		return nil, err
	}

	if len(b) < len(headerMagic)+4 {
		return nil, errors.New("state file is too small to be valid")
	}

	if !bytes.Equal(b[:len(headerMagic)], headerMagic[:]) {
		sf.header.NoErasureStorage = proto.Bool(true)
		if len(pw) > 0 {
			sf.header.Scrypt = new(Header_SCrypt)
			sf.header.KdfSalt = b[:32]
			if err := sf.deriveKey(pw); err != nil {
				return nil, err
			}
		}
		b = b[32:]
		state, err := sf.readOldStyle(b)
		if err != nil {
			return nil, err
		}
		return state, nil
	}

	b = b[len(headerMagic):]
	headerLen := binary.LittleEndian.Uint32(b)
	b = b[4:]
	if headerLen > 1<<16 {
		return nil, errors.New("state file corrupt")
	}
	if len(b) < int(headerLen) {
		return nil, errors.New("state file truncated")
	}
	headerBytes := b[:int(headerLen)]
	b = b[int(headerLen):]

	if err := proto.Unmarshal(headerBytes, &sf.header); err != nil {
		return nil, err
	}
	if len(pw) > 0 {
		if err := sf.deriveKey(pw); err != nil {
			return nil, err
		}
	}

	if !sf.header.GetNoErasureStorage() {
		for _, erasureMethod := range erasureRegistry {
			sf.Erasure = erasureMethod(&sf.header)
			if sf.Erasure != nil {
				break
			}
		}
		if sf.Erasure == nil {
			return nil, errors.New("unknown erasure storage method")
		}

		mask, err := sf.Erasure.Read(&sf.key)
		if err != nil {
			return nil, err
		}
		copy(sf.mask[:], mask[:])
	}

	smearedCopies := int(sf.header.GetNonceSmearCopies())

	if len(b) < 24*smearedCopies {
		return nil, errors.New("state file truncated")
	}

	var nonce [24]byte
	for i := 0; i < smearedCopies; i++ {
		for j := 0; j < 24; j++ {
			nonce[j] ^= b[24*i+j]
		}
	}

	b = b[24*smearedCopies:]

	var effectiveKey [kdfKeyLen]byte
	for i := range effectiveKey {
		effectiveKey[i] = sf.mask[i] ^ sf.key[i]
	}
	plaintext, ok := secretbox.Open(nil, b, &nonce, &effectiveKey)
	if !ok {
		return nil, BadPasswordError
	}
	if len(plaintext) < 4 {
		return nil, errors.New("state file corrupt")
	}
	length := binary.LittleEndian.Uint32(plaintext[:4])
	plaintext = plaintext[4:]
	if length > 1<<31 || length > uint32(len(plaintext)) {
		return nil, errors.New("state file corrupt")
	}
	plaintext = plaintext[:int(length)]

	var state State
	if err := proto.Unmarshal(plaintext, &state); err != nil {
		return nil, err
	}

	return &state, nil
}

func (sf *StateFile) readOldStyle(b []byte) (*State, error) {
	return loadOldState(b, &sf.key)
}

type NewState struct {
	State                []byte
	RotateErasureStorage bool
}

func (sf *StateFile) StartWriter(states chan NewState, done chan struct{}) {
	for {
		newState, ok := <-states
		if !ok {
			close(done)
			return
		}

		s := newState.State

		length := uint32(len(s)) + 4
		for i := uint(17); i < 32; i++ {
			if n := (uint32(1) << i); n >= length {
				length = n
				break
			}
		}

		plaintext := make([]byte, length)
		copy(plaintext[4:], s)
		if _, err := io.ReadFull(sf.Rand, plaintext[len(s)+4:]); err != nil {
			panic(err)
		}
		binary.LittleEndian.PutUint32(plaintext, uint32(len(s)))

		smearCopies := int(sf.header.GetNonceSmearCopies())
		nonceSmear := make([]byte, 24*smearCopies)
		if _, err := io.ReadFull(sf.Rand, nonceSmear[:]); err != nil {
			panic(err)
		}

		var nonce [24]byte
		for i := 0; i < smearCopies; i++ {
			for j := 0; j < 24; j++ {
				nonce[j] ^= nonceSmear[24*i+j]
			}
		}

		if sf.Erasure != nil && newState.RotateErasureStorage {
			var newMask [erasureKeyLen]byte
			if _, err := io.ReadFull(sf.Rand, newMask[:]); err != nil {
				panic(err)
			}
			if err := sf.Erasure.Write(&sf.key, &newMask); err != nil {
				sf.Log("Failed to write new erasure value: %s", err)
			} else {
				copy(sf.mask[:], newMask[:])
			}
		}

		var effectiveKey [kdfKeyLen]byte
		for i := range effectiveKey {
			effectiveKey[i] = sf.mask[i] ^ sf.key[i]
		}
		ciphertext := secretbox.Seal(nil, plaintext, &nonce, &effectiveKey)

		// Open a new, temporary, statefile
		out, err := os.OpenFile(sf.Path + ".tmp", os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0600)
		if err != nil {
			panic(err)
		}
		headerBytes, err := proto.Marshal(&sf.header)
		if err != nil {
			panic(err)
		}
		if _, err := out.Write(headerMagic[:]); err != nil {
			panic(err)
		}
		if err := binary.Write(out, binary.LittleEndian, uint32(len(headerBytes))); err != nil {
			panic(err)
		}
		if _, err := out.Write(headerBytes); err != nil {
			panic(err)
		}
		if _, err := out.Write(nonceSmear[:]); err != nil {
			panic(err)
		}
		if _, err := out.Write(ciphertext); err != nil {
			panic(err)
		}
		out.Close()

		// Remove any previous temporary statefile
		// (But this shouldn't ever happen?)
		if err := os.Remove(sf.Path + "~"); ! os.IsNotExist(err) {
			panic(err)
		}
		// Relink the old statefile to a temporary location
		if err := os.Rename(sf.Path, sf.Path + "~"); ! os.IsNotExist(err) {
			panic(err)
		}
		// Link the new statefile in place
		if err := os.Link(sf.Path + ".tmp", sf.Path); err != nil {
			panic(err)
		}
		// Remove the old statefile
		if err := os.Remove(sf.Path + ".tmp"); err != nil {
			panic(err)
		}
	}
}

type Lock struct {
	fd int
}

func (l *Lock) Close() {
	syscall.Flock(l.fd, syscall.LOCK_UN)
	syscall.Close(l.fd)
}

var BadPasswordError = errors.New("bad password")

func loadOldState(b []byte, key *[32]byte) (*State, error) {
	const (
		SCryptSaltLen = 32
		smearedCopies = 32768 / 24
	)

	if len(b) < SCryptSaltLen+24*smearedCopies {
		return nil, errors.New("state file is too small to be valid")
	}

	var nonce [24]byte
	for i := 0; i < smearedCopies; i++ {
		for j := 0; j < 24; j++ {
			nonce[j] ^= b[24*i+j]
		}
	}

	b = b[24*smearedCopies:]
	plaintext, ok := secretbox.Open(nil, b, &nonce, key)
	if !ok {
		return nil, BadPasswordError
	}
	if len(plaintext) < 4 {
		return nil, errors.New("state file corrupt")
	}
	length := binary.LittleEndian.Uint32(plaintext[:4])
	plaintext = plaintext[4:]
	if length > 1<<31 || length > uint32(len(plaintext)) {
		return nil, errors.New("state file corrupt")
	}
	plaintext = plaintext[:int(length)]

	var state State
	if err := proto.Unmarshal(plaintext, &state); err != nil {
		return nil, err
	}

	return &state, nil
}
<|endoftext|>


<commit_before>package logrus_syslog

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"log/syslog"
	"os"
)

// SyslogHook to send logs via syslog.
type SyslogHook struct {
	Writer        *syslog.Writer
	SyslogNetwork string
	SyslogRaddr   string
}

// Creates a hook to be added to an instance of logger. This is called with
// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
// `if err == nil { log.Hooks.Add(hook) }`
func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
	w, err := syslog.Dial(network, raddr, priority, tag)
	return &SyslogHook{w, network, raddr}, err
}

func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
	reader, err := entry.Reader()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
		return err
	}

	line := reader.String()

	switch entry.Data["level"] {
	case "panic":
		return hook.Writer.Crit(line)
	case "fatal":
		return hook.Writer.Crit(line)
	case "error":
		return hook.Writer.Err(line)
	case "warn":
		return hook.Writer.Warning(line)
	case "info":
		return hook.Writer.Info(line)
	case "debug":
		return hook.Writer.Debug(line)
	default:
		return nil
	}
}

func (hook *SyslogHook) Levels() []logrus.Level {
	return []logrus.Level{
		logrus.Panic,
		logrus.Fatal,
		logrus.Error,
		logrus.Warn,
		logrus.Info,
		logrus.Debug,
	}
}
<commit_msg>Call entry.String() directly.<commit_after>package logrus_syslog

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"log/syslog"
	"os"
)

// SyslogHook to send logs via syslog.
type SyslogHook struct {
	Writer        *syslog.Writer
	SyslogNetwork string
	SyslogRaddr   string
}

// Creates a hook to be added to an instance of logger. This is called with
// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
// `if err == nil { log.Hooks.Add(hook) }`
func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
	w, err := syslog.Dial(network, raddr, priority, tag)
	return &SyslogHook{w, network, raddr}, err
}

func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
	line, err := entry.String()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
		return err
	}

	switch entry.Data["level"] {
	case "panic":
		return hook.Writer.Crit(line)
	case "fatal":
		return hook.Writer.Crit(line)
	case "error":
		return hook.Writer.Err(line)
	case "warn":
		return hook.Writer.Warning(line)
	case "info":
		return hook.Writer.Info(line)
	case "debug":
		return hook.Writer.Debug(line)
	default:
		return nil
	}
}

func (hook *SyslogHook) Levels() []logrus.Level {
	return []logrus.Level{
		logrus.Panic,
		logrus.Fatal,
		logrus.Error,
		logrus.Warn,
		logrus.Info,
		logrus.Debug,
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.

// More information about Google Distance Matrix API is available on
// https://developers.google.com/maps/documentation/distancematrix/

package maps

import (
	"errors"
	"net/url"
	"strconv"
	"time"

	"golang.org/x/net/context"
)

var timezoneAPI = &apiConfig{
	host:            "https://maps.googleapis.com",
	path:            "/maps/api/timezone/json",
	acceptsClientID: true,
}

// Timezone makes a Timezone API request
func (c *Client) Timezone(ctx context.Context, r *TimezoneRequest) (*TimezoneResult, error) {
	if r.Location == nil {
		return nil, errors.New("maps: Location missing")
	}

	var response struct {
		TimezoneResult
		commonResponse
	}

	if err := c.getJSON(ctx, directionsAPI, r, &response); err != nil {
		return nil, err
	}

	if err := response.StatusError(); err != nil {
		return nil, err
	}

	return &response.TimezoneResult, nil
}

func (r *TimezoneRequest) params() url.Values {
	q := make(url.Values)
	q.Set("location", r.Location.String())
	q.Set("timestamp", strconv.FormatInt(r.Timestamp.Unix(), 10))
	if r.Language != "" {
		q.Set("language", r.Language)
	}
	return q
}

// TimezoneRequest is the request structure for Timezone API.
type TimezoneRequest struct {
	// Location represents the location to look up.
	Location *LatLng
	// Timestamp specifies the desired time. Time Zone API uses the timestamp to determine whether or not Daylight Savings should be applied.
	Timestamp time.Time
	// Language in which to return results.
	Language string
}

// TimezoneResult is a single geocoded address
type TimezoneResult struct {
	// DstOffset is the offset for daylight-savings time in seconds.
	DstOffset int `json:"dstOffset"`
	// RawOffset is the offset from UTC for the given location.
	RawOffset int `json:"rawOffset"`
	// TimeZoneID is a string containing the "tz" ID of the time zone.
	TimeZoneID string `json:"timeZoneId"`
	// TimeZoneName is a string containing the long form name of the time zone.
	TimeZoneName string `json:"timeZoneName"`
}
<commit_msg>fix timezone comment<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.

// More information about Google Distance Matrix API is available on
// https://developers.google.com/maps/documentation/distancematrix/

package maps

import (
	"errors"
	"net/url"
	"strconv"
	"time"

	"golang.org/x/net/context"
)

var timezoneAPI = &apiConfig{
	host:            "https://maps.googleapis.com",
	path:            "/maps/api/timezone/json",
	acceptsClientID: true,
}

// Timezone makes a Timezone API request
func (c *Client) Timezone(ctx context.Context, r *TimezoneRequest) (*TimezoneResult, error) {
	if r.Location == nil {
		return nil, errors.New("maps: Location missing")
	}

	var response struct {
		TimezoneResult
		commonResponse
	}

	if err := c.getJSON(ctx, directionsAPI, r, &response); err != nil {
		return nil, err
	}

	if err := response.StatusError(); err != nil {
		return nil, err
	}

	return &response.TimezoneResult, nil
}

func (r *TimezoneRequest) params() url.Values {
	q := make(url.Values)
	q.Set("location", r.Location.String())
	q.Set("timestamp", strconv.FormatInt(r.Timestamp.Unix(), 10))
	if r.Language != "" {
		q.Set("language", r.Language)
	}
	return q
}

// TimezoneRequest is the request structure for Timezone API.
type TimezoneRequest struct {
	// Location represents the location to look up.
	Location *LatLng
	// Timestamp specifies the desired time. Time Zone API uses the timestamp to determine whether or not Daylight Savings should be applied.
	Timestamp time.Time
	// Language in which to return results.
	Language string
}

// TimezoneResult is a single timezone result.
type TimezoneResult struct {
	// DstOffset is the offset for daylight-savings time in seconds.
	DstOffset int `json:"dstOffset"`
	// RawOffset is the offset from UTC for the given location.
	RawOffset int `json:"rawOffset"`
	// TimeZoneID is a string containing the "tz" ID of the time zone.
	TimeZoneID string `json:"timeZoneId"`
	// TimeZoneName is a string containing the long form name of the time zone.
	TimeZoneName string `json:"timeZoneName"`
}
<|endoftext|>


<commit_before>package bytebuffer

import "errors"

type ByteBuffer struct {
	pos    int
	buffer []byte
}

func NewByteBuffer(n int) *ByteBuffer {
	return &ByteBuffer{
		pos:    0,
		buffer: make([]byte, n),
	}
}

func NewByteBufferSlice(buffer []byte) *ByteBuffer {
	return &ByteBuffer{
		pos:    0,
		buffer: buffer,
	}
}

func (b *ByteBuffer) Pos() int { return b.pos }

func (b *ByteBuffer) SetPos(position int) {
	if position < 0 || position >= len(b.buffer) {
		// TODO: make a better error message
		panic(errors.New("Out of Range"))
	}

	b.pos = position
}

func (b *ByteBuffer) Len() int { return len(b.buffer) }

func (b *ByteBuffer) Buffer() []byte { return b.buffer }

func (b *ByteBuffer) Write(data []byte) {
	l := len(data)

	if b.Pos()+l > b.Len() {
		// TODO: make a better error message
		panic(errors.New("Overflow"))
	}

	for i := 0; i < l; i++ {
		b.buffer[b.pos+i] = data[i]
	}

	b.pos += l
}

func (b *ByteBuffer) WriteString(s string) {
	b.Write([]byte(s))
}

func (b *ByteBuffer) WriteUint32(val uint32) {
	b.Write([]byte{
		byte(val & 0xFF),
		byte((val >> 8) & 0xFF),
		byte((val >> 16) & 0xFF),
		byte(val >> 24),
	})
}

func (b *ByteBuffer) WriteUint64(val uint64) {
	b.WriteUint32(uint32(val & 0xFFFF))
	b.WriteUint32(uint32(val >> 32))
}

func (b *ByteBuffer) WriteInt32(val int32) {
	b.WriteUint32(uint32(val))
}

func (b *ByteBuffer) WriteInt64(val int64) {
	b.WriteUint64(uint64(val))
}

func (b *ByteBuffer) WriteInt(val int) {
	b.WriteUint32(uint32(val))
}
<commit_msg>bytebuffer: fix WriteUint64<commit_after>package bytebuffer

import "errors"

type ByteBuffer struct {
	pos    int
	buffer []byte
}

func NewByteBuffer(n int) *ByteBuffer {
	return &ByteBuffer{
		pos:    0,
		buffer: make([]byte, n),
	}
}

func NewByteBufferSlice(buffer []byte) *ByteBuffer {
	return &ByteBuffer{
		pos:    0,
		buffer: buffer,
	}
}

func (b *ByteBuffer) Pos() int { return b.pos }

func (b *ByteBuffer) SetPos(position int) {
	if position < 0 || position >= len(b.buffer) {
		// TODO: make a better error message
		panic(errors.New("Out of Range"))
	}

	b.pos = position
}

func (b *ByteBuffer) Len() int { return len(b.buffer) }

func (b *ByteBuffer) Buffer() []byte { return b.buffer }

func (b *ByteBuffer) Write(data []byte) {
	l := len(data)

	if b.Pos()+l > b.Len() {
		// TODO: make a better error message
		panic(errors.New("Overflow"))
	}

	for i := 0; i < l; i++ {
		b.buffer[b.pos+i] = data[i]
	}

	b.pos += l
}

func (b *ByteBuffer) WriteString(s string) {
	b.Write([]byte(s))
}

func (b *ByteBuffer) WriteUint32(val uint32) {
	b.Write([]byte{
		byte(val & 0xFF),
		byte((val >> 8) & 0xFF),
		byte((val >> 16) & 0xFF),
		byte(val >> 24),
	})
}

func (b *ByteBuffer) WriteUint64(val uint64) {
	b.WriteUint32(uint32(val & 0xFFFFFFFF))
	b.WriteUint32(uint32(val >> 32))
}

func (b *ByteBuffer) WriteInt32(val int32) {
	b.WriteUint32(uint32(val))
}

func (b *ByteBuffer) WriteInt64(val int64) {
	b.WriteUint64(uint64(val))
}

func (b *ByteBuffer) WriteInt(val int) {
	b.WriteUint32(uint32(val))
}
<|endoftext|>


<commit_before>package commandline

import (
	"errors"
	"strings"
)

func Parse(s string) *Command {
	ss := strings.Split(s, " ")
	if ss[0] == "" {
		return nil
	}
	return &Command{
		Name: ss[0],
		Args: ss[1:],
	}
}

type Command struct {
	Name string
	Args []string
}

type scanner struct {
	src  []byte
	size int
	off  int
}

func newScanner(src []byte) *scanner {
	return &scanner{
		src:  src,
		size: len(src),
	}
}

func (s *scanner) next() (byte, bool) {
	if s.off >= s.size {
		return 0, true
	}

	ret := s.src[s.off]

	s.off++
	return ret, false
}

func (s *scanner) lex() (*token, error) {
	ch, eof := s.next()
	if eof {
		return nil, nil
	}
	switch {
	case isIdent(ch):
		var ret []byte
		for isIdent(ch) {
			ch, eof = s.next()
			if eof {
				break
			}
			ret = append(ret, ch)
		}
		return &token{tt: ident, value: ret}, nil
	case ch == '"':
		var ret []byte
		for ch != '"' {
			ch, eof = s.next()
			if eof {
				return nil, errors.New("unexpected eof in string literal")
			}
			ret = append(ret, ch)
		}
		return &token{tt: str, value: ret}, nil
	case isWhitespace(ch):
		return s.lex()
	}
	return nil, errors.New("unexpected character")
}

func isWhitespace(r byte) bool {
	return r == ' '
}

func isIdent(r byte) bool {
	return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z'
}

type tokenType int

type token struct {
	tt    tokenType
	value []byte
}

const (
	ident tokenType = iota
	str
)
<commit_msg>Rename lex -> scan<commit_after>package commandline

import (
	"errors"
	"strings"
)

func Parse(s string) *Command {
	ss := strings.Split(s, " ")
	if ss[0] == "" {
		return nil
	}
	return &Command{
		Name: ss[0],
		Args: ss[1:],
	}
}

type Command struct {
	Name string
	Args []string
}

type scanner struct {
	src  []byte
	size int
	off  int
}

func newScanner(src []byte) *scanner {
	return &scanner{
		src:  src,
		size: len(src),
	}
}

func (s *scanner) next() (byte, bool) {
	if s.off >= s.size {
		return 0, true
	}

	ret := s.src[s.off]

	s.off++
	return ret, false
}

func (s *scanner) scan() (*token, error) {
	ch, eof := s.next()
	if eof {
		return nil, nil
	}
	switch {
	case isIdent(ch):
		var ret []byte
		for isIdent(ch) {
			ch, eof = s.next()
			if eof {
				break
			}
			ret = append(ret, ch)
		}
		return &token{tt: ident, value: ret}, nil
	case ch == '"':
		var ret []byte
		for ch != '"' {
			ch, eof = s.next()
			if eof {
				return nil, errors.New("unexpected eof in string literal")
			}
			ret = append(ret, ch)
		}
		return &token{tt: str, value: ret}, nil
	case isWhitespace(ch):
		return s.scan()
	}
	return nil, errors.New("unexpected character")
}

func isWhitespace(r byte) bool {
	return r == ' '
}

func isIdent(r byte) bool {
	return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z'
}

type tokenType int

type token struct {
	tt    tokenType
	value []byte
}

const (
	ident tokenType = iota
	str
)
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/gob"
	"errors"
	"fmt"
	"log"
	"os"
	"strconv"

	"github.com/boltdb/bolt"
)

var db = dbSetup()

type (
	Config struct {
		ID   int
		Info ConfigInfo
	}

	ConfigInfo struct {
		URL       string
		DBName    string
		OdooPass  string // Odoo Master Password
		BackupDir string
		Version   float64
	}
)

func dbSetup() *bolt.DB {
	dbDir := os.Getenv("HOME") + "/.odoobup"
	dbPath := dbDir + "/config.db"

	//check if .odoobup directory not found
	if _, err := os.Stat(dbDir); os.IsNotExist(err) {
		err := os.Mkdir(dbDir, 0777)
		if err != nil {
			log.Fatalln(err)
		}
	}

	//create and open a database
	db, err := bolt.Open(dbPath, 0777, nil)
	if err != nil {
		log.Fatalln(err)
	}

	//create config bucket
	db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists([]byte("config"))
		if err != nil {
			log.Fatalln(err)
		}
		return nil
	})

	return db
}

func (c *Config) MarshalBinary() (data []byte, err error) {
	w := new(bytes.Buffer)
	encoder := gob.NewEncoder(w)
	err = encoder.Encode(c.Info)
	if err != nil {
		return nil, err
	}
	return w.Bytes(), nil
}

func (c *Config) UnmarshalBinary(data []byte) error {
	r := bytes.NewBuffer(data)
	decoder := gob.NewDecoder(r)
	return decoder.Decode(&c.Info)
}

func NewConfig(ci *ConfigInfo) (*Config, error) {
	var c Config

	err := db.Update(func(tx *bolt.Tx) error {
		bkt := tx.Bucket([]byte("config"))

		seq, _ := bkt.NextSequence()
		c.ID = int(seq)
		c.Info = *ci

		encoding, err := c.MarshalBinary()
		if err != nil {
			return err
		}

		if err := bkt.Put(itob(c.ID), encoding); err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	return &c, nil
}

func ConfigByID(id int) (*Config, error) {
	var config Config

	err := db.View(func(tx *bolt.Tx) error {
		v := tx.Bucket([]byte("config")).Get(itob(id))
		if v == nil {
			idStr := fmt.Sprint(id)
			return errors.New("The ID " + idStr + " was not Found")
		}

		if err := config.UnmarshalBinary(v); err != nil {
			return err
		}
		config.ID = id

		return nil
	})
	if err != nil {
		return nil, err
	}

	return &config, nil
}

func AllConfig() ([]Config, error) {
	var config Config
	var allConfig []Config

	err := db.View(func(tx *bolt.Tx) error {
		if err := tx.Bucket([]byte("config")).ForEach(func(k, v []byte) error {
			config.ID, _ = strconv.Atoi(string(k))
			if err := config.UnmarshalBinary(v); err != nil {
				return err
			}

			allConfig = append(allConfig, config)

			return nil

		}); err != nil {
			return err
		}

		return nil

	})
	if err != nil {
		return nil, err
	}

	return allConfig, nil
}

func DeleteConfig(id int) error {
	return db.Update(func(tx *bolt.Tx) error {
		return tx.Bucket([]byte("config")).Delete(itob(id))
	})
}

func itob(v int) []byte {
	id := fmt.Sprintf("%08d", v)
	return []byte(id)
}
<commit_msg>change MarshalBinary UnmarshalBinary methods names<commit_after>package main

import (
	"bytes"
	"encoding/gob"
	"errors"
	"fmt"
	"log"
	"os"
	"strconv"

	"github.com/boltdb/bolt"
)

var db = dbSetup()

type (
	Config struct {
		ID   int
		Info ConfigInfo
	}

	ConfigInfo struct {
		URL       string
		DBName    string
		OdooPass  string // Odoo Master Password
		BackupDir string
		Version   float64
	}
)

func dbSetup() *bolt.DB {
	dbDir := os.Getenv("HOME") + "/.odoobup"
	dbPath := dbDir + "/config.db"

	//check if .odoobup directory not found
	if _, err := os.Stat(dbDir); os.IsNotExist(err) {
		err := os.Mkdir(dbDir, 0777)
		if err != nil {
			log.Fatalln(err)
		}
	}

	//create and open a database
	db, err := bolt.Open(dbPath, 0777, nil)
	if err != nil {
		log.Fatalln(err)
	}

	//create config bucket
	db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists([]byte("config"))
		if err != nil {
			log.Fatalln(err)
		}
		return nil
	})

	return db
}

func (c *Config) Encode() (data []byte, err error) {
	w := new(bytes.Buffer)
	encoder := gob.NewEncoder(w)
	err = encoder.Encode(c.Info)
	if err != nil {
		return nil, err
	}
	return w.Bytes(), nil
}

func (c *Config) Decode(data []byte) error {
	r := bytes.NewBuffer(data)
	decoder := gob.NewDecoder(r)
	return decoder.Decode(&c.Info)
}

func NewConfig(ci *ConfigInfo) (*Config, error) {
	var c Config

	err := db.Update(func(tx *bolt.Tx) error {
		bkt := tx.Bucket([]byte("config"))

		seq, _ := bkt.NextSequence()
		c.ID = int(seq)
		c.Info = *ci

		encoding, err := c.Encode()
		if err != nil {
			return err
		}

		if err := bkt.Put(itob(c.ID), encoding); err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	return &c, nil
}

func ConfigByID(id int) (*Config, error) {
	var config Config

	err := db.View(func(tx *bolt.Tx) error {
		v := tx.Bucket([]byte("config")).Get(itob(id))
		if v == nil {
			idStr := fmt.Sprint(id)
			return errors.New("The ID " + idStr + " was not Found")
		}

		if err := config.Decode(v); err != nil {
			return err
		}
		config.ID = id

		return nil
	})
	if err != nil {
		return nil, err
	}

	return &config, nil
}

func AllConfig() ([]Config, error) {
	var config Config
	var allConfig []Config

	err := db.View(func(tx *bolt.Tx) error {
		if err := tx.Bucket([]byte("config")).ForEach(func(k, v []byte) error {
			config.ID, _ = strconv.Atoi(string(k))
			if err := config.Decode(v); err != nil {
				return err
			}

			allConfig = append(allConfig, config)

			return nil

		}); err != nil {
			return err
		}

		return nil

	})
	if err != nil {
		return nil, err
	}

	return allConfig, nil
}

func DeleteConfig(id int) error {
	return db.Update(func(tx *bolt.Tx) error {
		return tx.Bucket([]byte("config")).Delete(itob(id))
	})
}

func itob(v int) []byte {
	id := fmt.Sprintf("%08d", v)
	return []byte(id)
}
<|endoftext|>