<commit_before>package code39

import (
	"errors"
	"github.com/boombuler/barcode"
	"github.com/boombuler/barcode/utils"
	"strings"
)

type encodeInfo struct {
	value int
	data  []bool
}

var encodeTable map[rune]encodeInfo = map[rune]encodeInfo{
	'0': encodeInfo{0, []bool{true, false, true, false, false, true, true, false, true, true, false, true}},
	'1': encodeInfo{1, []bool{true, true, false, true, false, false, true, false, true, false, true, true}},
	'2': encodeInfo{2, []bool{true, false, true, true, false, false, true, false, true, false, true, true}},
	'3': encodeInfo{3, []bool{true, true, false, true, true, false, false, true, false, true, false, true}},
	'4': encodeInfo{4, []bool{true, false, true, false, false, true, true, false, true, false, true, true}},
	'5': encodeInfo{5, []bool{true, true, false, true, false, false, true, true, false, true, false, true}},
	'6': encodeInfo{6, []bool{true, false, true, true, false, false, true, true, false, true, false, true}},
	'7': encodeInfo{7, []bool{true, false, true, false, false, true, false, true, true, false, true, true}},
	'8': encodeInfo{8, []bool{true, true, false, true, false, false, true, false, true, true, false, true}},
	'9': encodeInfo{9, []bool{true, false, true, true, false, false, true, false, true, true, false, true}},
	'A': encodeInfo{10, []bool{true, true, false, true, false, true, false, false, true, false, true, true}},
	'B': encodeInfo{11, []bool{true, false, true, true, false, true, false, false, true, false, true, true}},
	'C': encodeInfo{12, []bool{true, true, false, true, true, false, true, false, false, true, false, true}},
	'D': encodeInfo{13, []bool{true, false, true, false, true, true, false, false, true, false, true, true}},
	'E': encodeInfo{14, []bool{true, true, false, true, false, true, true, false, false, true, false, true}},
	'F': encodeInfo{15, []bool{true, false, true, true, false, true, true, false, false, true, false, true}},
	'G': encodeInfo{16, []bool{true, false, true, false, true, false, false, true, true, false, true, true}},
	'H': encodeInfo{17, []bool{true, true, false, true, false, true, false, false, true, true, false, true}},
	'I': encodeInfo{18, []bool{true, false, true, true, false, true, false, false, true, true, false, true}},
	'J': encodeInfo{19, []bool{true, false, true, false, true, true, false, false, true, true, false, true}},
	'K': encodeInfo{20, []bool{true, true, false, true, false, true, false, true, false, false, true, true}},
	'L': encodeInfo{21, []bool{true, false, true, true, false, true, false, true, false, false, true, true}},
	'M': encodeInfo{22, []bool{true, true, false, true, true, false, true, false, true, false, false, true}},
	'N': encodeInfo{23, []bool{true, false, true, false, true, true, false, true, false, false, true, true}},
	'O': encodeInfo{24, []bool{true, true, false, true, false, true, true, false, true, false, false, true}},
	'P': encodeInfo{25, []bool{true, false, true, true, false, true, true, false, true, false, false, true}},
	'Q': encodeInfo{26, []bool{true, false, true, false, true, false, true, true, false, false, true, true}},
	'R': encodeInfo{27, []bool{true, true, false, true, false, true, false, true, true, false, false, true}},
	'S': encodeInfo{28, []bool{true, false, true, true, false, true, false, true, true, false, false, true}},
	'T': encodeInfo{29, []bool{true, false, true, false, true, true, false, true, true, false, false, true}},
	'U': encodeInfo{30, []bool{true, true, false, false, true, false, true, false, true, false, true, true}},
	'V': encodeInfo{31, []bool{true, false, false, true, true, false, true, false, true, false, true, true}},
	'W': encodeInfo{32, []bool{true, true, false, false, true, true, false, true, false, true, false, true}},
	'X': encodeInfo{33, []bool{true, false, false, true, false, true, true, false, true, false, true, true}},
	'Y': encodeInfo{34, []bool{true, true, false, false, true, false, true, true, false, true, false, true}},
	'Z': encodeInfo{35, []bool{true, false, false, true, true, false, true, true, false, true, false, true}},
	'-': encodeInfo{36, []bool{true, false, false, true, false, true, false, true, true, false, true, true}},
	'.': encodeInfo{37, []bool{true, true, false, false, true, false, true, false, true, true, false, true}},
	' ': encodeInfo{38, []bool{true, false, false, true, true, false, true, false, true, true, false, true}},
	'$': encodeInfo{39, []bool{true, false, false, true, false, false, true, false, false, true, false, true}},
	'/': encodeInfo{40, []bool{true, false, false, true, false, false, true, false, true, false, false, true}},
	'+': encodeInfo{41, []bool{true, false, false, true, false, true, false, false, true, false, false, true}},
	'%': encodeInfo{42, []bool{true, false, true, false, false, true, false, false, true, false, false, true}},
	'*': encodeInfo{-1, []bool{true, false, false, true, false, true, true, false, true, true, false, true}},
}

func getChecksum(content string) string {
	sum := 0
	for _, r := range content {
		info, ok := encodeTable[r]
		if !ok || info.value < 0 {
			return "#"
		}

		sum += info.value
	}

	sum = sum % 43
	for r, v := range encodeTable {
		if v.value == sum {
			return string(r)
		}
	}
	return "#"
}

// encodes the given string as a code39 barcode
// if includeChecksum is set to true, a checksum character is calculated and added to the content
func Encode(content string, includeChecksum bool) (barcode.Barcode, error) {
	if strings.ContainsRune(content, '*') {
		return nil, errors.New("invalid data")
	}

	data := "*" + content
	if includeChecksum {
		data += getChecksum(content)
	}
	data += "*"

	result := new(utils.BitList)

	for i, r := range data {
		if i != 0 {
			result.AddBit(false)
		}

		info, ok := encodeTable[r]
		if !ok {
			return nil, errors.New("invalid data")
		}
		result.AddBit(info.data...)
	}

	return utils.New1DCode("Code 39", content, result), nil
}
<commit_msg>added code39 full ASCII mode<commit_after>package code39

import (
	"errors"
	"github.com/boombuler/barcode"
	"github.com/boombuler/barcode/utils"
	"strings"
)

type encodeInfo struct {
	value int
	data  []bool
}

var encodeTable map[rune]encodeInfo = map[rune]encodeInfo{
	'0': encodeInfo{0, []bool{true, false, true, false, false, true, true, false, true, true, false, true}},
	'1': encodeInfo{1, []bool{true, true, false, true, false, false, true, false, true, false, true, true}},
	'2': encodeInfo{2, []bool{true, false, true, true, false, false, true, false, true, false, true, true}},
	'3': encodeInfo{3, []bool{true, true, false, true, true, false, false, true, false, true, false, true}},
	'4': encodeInfo{4, []bool{true, false, true, false, false, true, true, false, true, false, true, true}},
	'5': encodeInfo{5, []bool{true, true, false, true, false, false, true, true, false, true, false, true}},
	'6': encodeInfo{6, []bool{true, false, true, true, false, false, true, true, false, true, false, true}},
	'7': encodeInfo{7, []bool{true, false, true, false, false, true, false, true, true, false, true, true}},
	'8': encodeInfo{8, []bool{true, true, false, true, false, false, true, false, true, true, false, true}},
	'9': encodeInfo{9, []bool{true, false, true, true, false, false, true, false, true, true, false, true}},
	'A': encodeInfo{10, []bool{true, true, false, true, false, true, false, false, true, false, true, true}},
	'B': encodeInfo{11, []bool{true, false, true, true, false, true, false, false, true, false, true, true}},
	'C': encodeInfo{12, []bool{true, true, false, true, true, false, true, false, false, true, false, true}},
	'D': encodeInfo{13, []bool{true, false, true, false, true, true, false, false, true, false, true, true}},
	'E': encodeInfo{14, []bool{true, true, false, true, false, true, true, false, false, true, false, true}},
	'F': encodeInfo{15, []bool{true, false, true, true, false, true, true, false, false, true, false, true}},
	'G': encodeInfo{16, []bool{true, false, true, false, true, false, false, true, true, false, true, true}},
	'H': encodeInfo{17, []bool{true, true, false, true, false, true, false, false, true, true, false, true}},
	'I': encodeInfo{18, []bool{true, false, true, true, false, true, false, false, true, true, false, true}},
	'J': encodeInfo{19, []bool{true, false, true, false, true, true, false, false, true, true, false, true}},
	'K': encodeInfo{20, []bool{true, true, false, true, false, true, false, true, false, false, true, true}},
	'L': encodeInfo{21, []bool{true, false, true, true, false, true, false, true, false, false, true, true}},
	'M': encodeInfo{22, []bool{true, true, false, true, true, false, true, false, true, false, false, true}},
	'N': encodeInfo{23, []bool{true, false, true, false, true, true, false, true, false, false, true, true}},
	'O': encodeInfo{24, []bool{true, true, false, true, false, true, true, false, true, false, false, true}},
	'P': encodeInfo{25, []bool{true, false, true, true, false, true, true, false, true, false, false, true}},
	'Q': encodeInfo{26, []bool{true, false, true, false, true, false, true, true, false, false, true, true}},
	'R': encodeInfo{27, []bool{true, true, false, true, false, true, false, true, true, false, false, true}},
	'S': encodeInfo{28, []bool{true, false, true, true, false, true, false, true, true, false, false, true}},
	'T': encodeInfo{29, []bool{true, false, true, false, true, true, false, true, true, false, false, true}},
	'U': encodeInfo{30, []bool{true, true, false, false, true, false, true, false, true, false, true, true}},
	'V': encodeInfo{31, []bool{true, false, false, true, true, false, true, false, true, false, true, true}},
	'W': encodeInfo{32, []bool{true, true, false, false, true, true, false, true, false, true, false, true}},
	'X': encodeInfo{33, []bool{true, false, false, true, false, true, true, false, true, false, true, true}},
	'Y': encodeInfo{34, []bool{true, true, false, false, true, false, true, true, false, true, false, true}},
	'Z': encodeInfo{35, []bool{true, false, false, true, true, false, true, true, false, true, false, true}},
	'-': encodeInfo{36, []bool{true, false, false, true, false, true, false, true, true, false, true, true}},
	'.': encodeInfo{37, []bool{true, true, false, false, true, false, true, false, true, true, false, true}},
	' ': encodeInfo{38, []bool{true, false, false, true, true, false, true, false, true, true, false, true}},
	'$': encodeInfo{39, []bool{true, false, false, true, false, false, true, false, false, true, false, true}},
	'/': encodeInfo{40, []bool{true, false, false, true, false, false, true, false, true, false, false, true}},
	'+': encodeInfo{41, []bool{true, false, false, true, false, true, false, false, true, false, false, true}},
	'%': encodeInfo{42, []bool{true, false, true, false, false, true, false, false, true, false, false, true}},
	'*': encodeInfo{-1, []bool{true, false, false, true, false, true, true, false, true, true, false, true}},
}

var extendedTable map[rune]string = map[rune]string{
	0: `%U`, 1: `$A`, 2: `$B`, 3: `$C`, 4: `$D`, 5: `$E`, 6: `$F`, 7: `$G`, 8: `$H`, 9: `$I`, 10: `$J`,
	11: `$K`, 12: `$L`, 13: `$M`, 14: `$N`, 15: `$O`, 16: `$P`, 17: `$Q`, 18: `$R`, 19: `$S`, 20: `$T`,
	21: `$U`, 22: `$V`, 23: `$W`, 24: `$X`, 25: `$Y`, 26: `$Z`, 27: `%A`, 28: `%B`, 29: `%C`, 30: `%D`,
	31: `%E`, 33: `/A`, 34: `/B`, 35: `/C`, 36: `/D`, 37: `/E`, 38: `/F`, 39: `/G`, 40: `/H`, 41: `/I`,
	42: `/J`, 43: `/K`, 44: `/L`, 47: `/O`, 58: `/Z`, 59: `%F`, 60: `%G`, 61: `%H`, 62: `%I`, 63: `%J`,
	64: `%V`, 91: `%K`, 92: `%L`, 93: `%M`, 94: `%N`, 95: `%O`, 96: `%W`, 97: `+A`, 98: `+B`, 99: `+C`,
	100: `+D`, 101: `+E`, 102: `+F`, 103: `+G`, 104: `+H`, 105: `+I`, 106: `+J`, 107: `+K`, 108: `+L`,
	109: `+M`, 110: `+N`, 111: `+O`, 112: `+P`, 113: `+Q`, 114: `+R`, 115: `+S`, 116: `+T`, 117: `+U`,
	118: `+V`, 119: `+W`, 120: `+X`, 121: `+Y`, 122: `+Z`, 123: `%P`, 124: `%Q`, 125: `%R`, 126: `%S`,
	127: `%T`,
}

func getChecksum(content string) string {
	sum := 0
	for _, r := range content {
		info, ok := encodeTable[r]
		if !ok || info.value < 0 {
			return "#"
		}

		sum += info.value
	}

	sum = sum % 43
	for r, v := range encodeTable {
		if v.value == sum {
			return string(r)
		}
	}
	return "#"
}

func prepare(content string) (string, error) {
	result := ""
	for _, r := range content {
		if r > 127 {
			return "", errors.New("Only ASCII strings can be encoded")
		}
		val, ok := extendedTable[r]
		if ok {
			result += val
		} else {
			result += string([]rune{r})
		}
	}
	return result, nil
}

// encodes the given string as a code39 barcode
// if includeChecksum is set to true, a checksum character is calculated and added to the content
func Encode(content string, includeChecksum bool, fullASCIIMode bool) (barcode.Barcode, error) {
	if fullASCIIMode {
		var err error
		content, err = prepare(content)
		if err != nil {
			return nil, err
		}
	} else if strings.ContainsRune(content, '*') {
		return nil, errors.New("invalid data! try full ascii mode")
	}

	data := "*" + content
	if includeChecksum {
		data += getChecksum(content)
	}
	data += "*"

	result := new(utils.BitList)

	for i, r := range data {
		if i != 0 {
			result.AddBit(false)
		}

		info, ok := encodeTable[r]
		if !ok {
			return nil, errors.New("invalid data! try full ascii mode")
		}
		result.AddBit(info.data...)
	}

	return utils.New1DCode("Code 39", content, result), nil
}
<|endoftext|>


<commit_before>package tview

import (
	"github.com/gdamore/tcell"
)

// page represents one page of a Pages object.
type page struct {
	Name    string    // The page's name.
	Item    Primitive // The page's primitive.
	Resize  bool      // Whether or not to resize the page when it is drawn.
	Visible bool      // Whether or not this page is visible.
}

// Pages is a container for other primitives often used as the application's
// root primitive. It allows to easily switch the visibility of the contained
// primitives.
type Pages struct {
	*Box

	// The contained pages.
	pages []*page

	// We keep a reference to the function which allows us to set the focus to
	// a newly visible page.
	setFocus func(p Primitive)

	// An optional handler which is called whenever the visibility or the order of
	// pages changes.
	changed func()
}

// NewPages returns a new Pages object.
func NewPages() *Pages {
	p := &Pages{
		Box: NewBox(),
	}
	p.focus = p
	return p
}

// SetChangedFunc sets a handler which is called whenever the visibility or the
// order of any visible pages changes. This can be used to redraw the pages.
func (p *Pages) SetChangedFunc(handler func()) *Pages {
	p.changed = handler
	return p
}

// AddPage adds a new page with the given name and primitive. Leaving the name
// empty or using the same name for multiple items may cause conflicts in other
// functions.
//
// Visible pages will be drawn in the order they were added (unless that order
// was changed in one of the other functions). If "resize" is set to true, the
// primitive will be set to the size available to the Pages primitive whenever
// the pages are drawn.
func (p *Pages) AddPage(name string, item Primitive, resize, visible bool) *Pages {
	p.pages = append(p.pages, &page{Item: item, Name: name, Resize: resize, Visible: visible})
	if p.changed != nil {
		p.changed()
	}
	p.refocus()
	return p
}

// RemovePage removes the page with the given name.
func (p *Pages) RemovePage(name string) *Pages {
	for index, page := range p.pages {
		if page.Name == name {
			p.pages = append(p.pages[:index], p.pages[index+1:]...)
			if page.Visible && p.changed != nil {
				p.changed()
			}
			break
		}
	}
	p.refocus()
	return p
}

// ShowPage sets a page's visibility to "true" (in addition to any other pages
// which are already visible).
func (p *Pages) ShowPage(name string) *Pages {
	for _, page := range p.pages {
		if page.Name == name {
			page.Visible = true
			if p.changed != nil {
				p.changed()
			}
			break
		}
	}
	p.refocus()
	return p
}

// HidePage sets a page's visibility to "false".
func (p *Pages) HidePage(name string) *Pages {
	for _, page := range p.pages {
		if page.Name == name {
			page.Visible = false
			if p.changed != nil {
				p.changed()
			}
			break
		}
	}
	p.refocus()
	return p
}

// SwitchToPage sets a page's visibility to "true" and all other pages'
// visibility to "false".
func (p *Pages) SwitchToPage(name string) *Pages {
	for _, page := range p.pages {
		if page.Name == name {
			page.Visible = true
		} else {
			page.Visible = false
		}
	}
	if p.changed != nil {
		p.changed()
	}
	p.refocus()
	return p
}

// SendToFront changes the order of the pages such that the page with the given
// name comes last, causing it to be drawn last with the next update (if
// visible).
func (p *Pages) SendToFront(name string) *Pages {
	for index, page := range p.pages {
		if page.Name == name {
			if index < len(p.pages)-1 {
				p.pages = append(append(p.pages[:index], p.pages[index+1:]...), page)
			}
			if page.Visible && p.changed != nil {
				p.changed()
			}
			break
		}
	}
	p.refocus()
	return p
}

// SendToBack changes the order of the pages such that the page with the given
// name comes first, causing it to be drawn first with the next update (if
// visible).
func (p *Pages) SendToBack(name string) *Pages {
	for index, pg := range p.pages {
		if pg.Name == name {
			if index > 0 {
				p.pages = append(append([]*page{pg}, p.pages[:index]...), p.pages[index+1:]...)
			}
			if pg.Visible && p.changed != nil {
				p.changed()
			}
			break
		}
	}
	p.refocus()
	return p
}

// HasFocus returns whether or not this primitive has focus.
func (p *Pages) HasFocus() bool {
	for _, page := range p.pages {
		if page.Item.GetFocusable().HasFocus() {
			return true
		}
	}
	return false
}

// Focus is called by the application when the primitive receives focus.
func (p *Pages) Focus(delegate func(p Primitive)) {
	p.setFocus = delegate
	var topItem Primitive
	for _, page := range p.pages {
		if page.Visible {
			topItem = page.Item
		}
	}
	if topItem != nil {
		delegate(topItem)
	}
}

// refocus sets the focus to the topmost visible page but only if we have focus.
func (p *Pages) refocus() {
	if !p.HasFocus() || p.setFocus == nil {
		return
	}
	var topItem Primitive
	for _, page := range p.pages {
		if page.Visible {
			topItem = page.Item
		}
	}
	if topItem != nil {
		p.setFocus(topItem)
	}
}

// Draw draws this primitive onto the screen.
func (p *Pages) Draw(screen tcell.Screen) {
	for _, page := range p.pages {
		if !page.Visible {
			continue
		}
		if page.Resize {
			x, y, width, height := p.GetInnerRect()
			page.Item.SetRect(x, y, width, height)
		}
		page.Item.Draw(screen)
	}
}
<commit_msg>Bugfix in pages focus.<commit_after>package tview

import (
	"github.com/gdamore/tcell"
)

// page represents one page of a Pages object.
type page struct {
	Name    string    // The page's name.
	Item    Primitive // The page's primitive.
	Resize  bool      // Whether or not to resize the page when it is drawn.
	Visible bool      // Whether or not this page is visible.
}

// Pages is a container for other primitives often used as the application's
// root primitive. It allows to easily switch the visibility of the contained
// primitives.
type Pages struct {
	*Box

	// The contained pages.
	pages []*page

	// We keep a reference to the function which allows us to set the focus to
	// a newly visible page.
	setFocus func(p Primitive)

	// An optional handler which is called whenever the visibility or the order of
	// pages changes.
	changed func()
}

// NewPages returns a new Pages object.
func NewPages() *Pages {
	p := &Pages{
		Box: NewBox(),
	}
	p.focus = p
	return p
}

// SetChangedFunc sets a handler which is called whenever the visibility or the
// order of any visible pages changes. This can be used to redraw the pages.
func (p *Pages) SetChangedFunc(handler func()) *Pages {
	p.changed = handler
	return p
}

// AddPage adds a new page with the given name and primitive. Leaving the name
// empty or using the same name for multiple items may cause conflicts in other
// functions.
//
// Visible pages will be drawn in the order they were added (unless that order
// was changed in one of the other functions). If "resize" is set to true, the
// primitive will be set to the size available to the Pages primitive whenever
// the pages are drawn.
func (p *Pages) AddPage(name string, item Primitive, resize, visible bool) *Pages {
	p.pages = append(p.pages, &page{Item: item, Name: name, Resize: resize, Visible: visible})
	if p.changed != nil {
		p.changed()
	}
	p.refocus()
	return p
}

// RemovePage removes the page with the given name.
func (p *Pages) RemovePage(name string) *Pages {
	for index, page := range p.pages {
		if page.Name == name {
			p.pages = append(p.pages[:index], p.pages[index+1:]...)
			if page.Visible && p.changed != nil {
				p.changed()
			}
			break
		}
	}
	p.refocus()
	return p
}

// ShowPage sets a page's visibility to "true" (in addition to any other pages
// which are already visible).
func (p *Pages) ShowPage(name string) *Pages {
	for _, page := range p.pages {
		if page.Name == name {
			page.Visible = true
			if p.changed != nil {
				p.changed()
			}
			break
		}
	}
	p.refocus()
	return p
}

// HidePage sets a page's visibility to "false".
func (p *Pages) HidePage(name string) *Pages {
	for _, page := range p.pages {
		if page.Name == name {
			page.Visible = false
			if p.changed != nil {
				p.changed()
			}
			break
		}
	}
	p.refocus()
	return p
}

// SwitchToPage sets a page's visibility to "true" and all other pages'
// visibility to "false".
func (p *Pages) SwitchToPage(name string) *Pages {
	for _, page := range p.pages {
		if page.Name == name {
			page.Visible = true
		} else {
			page.Visible = false
		}
	}
	if p.changed != nil {
		p.changed()
	}
	p.refocus()
	return p
}

// SendToFront changes the order of the pages such that the page with the given
// name comes last, causing it to be drawn last with the next update (if
// visible).
func (p *Pages) SendToFront(name string) *Pages {
	for index, page := range p.pages {
		if page.Name == name {
			if index < len(p.pages)-1 {
				p.pages = append(append(p.pages[:index], p.pages[index+1:]...), page)
			}
			if page.Visible && p.changed != nil {
				p.changed()
			}
			break
		}
	}
	p.refocus()
	return p
}

// SendToBack changes the order of the pages such that the page with the given
// name comes first, causing it to be drawn first with the next update (if
// visible).
func (p *Pages) SendToBack(name string) *Pages {
	for index, pg := range p.pages {
		if pg.Name == name {
			if index > 0 {
				p.pages = append(append([]*page{pg}, p.pages[:index]...), p.pages[index+1:]...)
			}
			if pg.Visible && p.changed != nil {
				p.changed()
			}
			break
		}
	}
	p.refocus()
	return p
}

// HasFocus returns whether or not this primitive has focus.
func (p *Pages) HasFocus() bool {
	for _, page := range p.pages {
		if page.Item.GetFocusable().HasFocus() {
			return true
		}
	}
	return false
}

// Focus is called by the application when the primitive receives focus.
func (p *Pages) Focus(delegate func(p Primitive)) {
	p.setFocus = delegate
	var topItem Primitive
	for _, page := range p.pages {
		if page.Visible {
			topItem = page.Item
		}
	}
	if topItem != nil {
		delegate(topItem)
	}
}

// refocus sets the focus to the topmost visible page but only if we have focus.
func (p *Pages) refocus() {
	var (
		topItem  Primitive
		hasFocus bool
	)
	for _, page := range p.pages {
		if page.Item.GetFocusable().HasFocus() {
			hasFocus = true
		}
		if page.Visible {
			topItem = page.Item
		}
	}
	if hasFocus && p.setFocus != nil && topItem != nil {
		p.setFocus(topItem)
	}
}

// Draw draws this primitive onto the screen.
func (p *Pages) Draw(screen tcell.Screen) {
	for _, page := range p.pages {
		if !page.Visible {
			continue
		}
		if page.Resize {
			x, y, width, height := p.GetInnerRect()
			page.Item.SetRect(x, y, width, height)
		}
		page.Item.Draw(screen)
	}
}
<|endoftext|>


<commit_before>package golangQL

import (
	"bytes"
	"errors"
	"regexp"
	"strings"
)

const (
	openComma     = '{'
	closeComma    = '}'
	baseFieldName = "data"
	space         = ' '
)

var (
	ErrWrongGQLFormat = errors.New("errors.GQLWrongFormat")
)

func parse(query string) (*node, error) {
	query, err := formatQuery(query)
	if err != nil {
		return nil, err
	}

	tree := newNode(baseFieldName)
	currentNode := tree

	var buf bytes.Buffer
	for _, char := range query {
		switch char {
		case openComma:
			newNode := newNode(buf.String())
			newNode.parent = currentNode
			currentNode.appendChild(newNode)

			currentNode = newNode

			buf.Reset()
		case closeComma:
			if currentNode.parent == nil {
				return nil, ErrWrongGQLFormat
			}

			currentNode = currentNode.parent
		case space:
			currentNode.fields = append(currentNode.fields, buf.String())
			buf.Reset()
		default:
			buf.WriteRune(char)
		}
	}

	return tree, nil
}

func formatQuery(query string) (string, error) {
	if len(query) == 0 {
		return "", ErrWrongGQLFormat
	}

	query = strings.Replace(query, "}", " }", -1)

	query, err := deleteDoubleSpaces(query)
	if err != nil {
		return "", err
	}

	if query[0] != openComma || query[len(query)-1] != closeComma {
		return "", ErrWrongGQLFormat
	}

	query = strings.Replace(query, "{ ", "{", -1)
	query = strings.Replace(query, " {", "{", -1)
	query = strings.Replace(query, "} ", "}", -1)
	query = strings.Trim(query, "{}")

	return query, nil
}

func deleteDoubleSpaces(str string) (string, error) {
	str = strings.TrimSpace(str)
	r, err := regexp.Compile("( )+")
	if err != nil {
		return "", err
	}
	str = r.ReplaceAllString(str, " ")

	return str, nil
}
<commit_msg>improved perfomance<commit_after>package golangQL

import (
	"bytes"
	"errors"
	"regexp"
	"strings"
)

const (
	openComma     = '{'
	closeComma    = '}'
	baseFieldName = "data"
	space         = ' '
)

var (
	ErrWrongGQLFormat = errors.New("errors.GQLWrongFormat")
	spacesRegEx = regexp.MustCompile("( )+")
)

func parse(query string) (*node, error) {
	query, err := formatQuery(query)
	if err != nil {
		return nil, err
	}

	tree := newNode(baseFieldName)
	currentNode := tree

	var buf bytes.Buffer
	for _, char := range query {
		switch char {
		case openComma:
			newNode := newNode(buf.String())
			newNode.parent = currentNode
			currentNode.appendChild(newNode)

			currentNode = newNode

			buf.Reset()
		case closeComma:
			if currentNode.parent == nil {
				return nil, ErrWrongGQLFormat
			}

			currentNode = currentNode.parent
		case space:
			currentNode.fields = append(currentNode.fields, buf.String())
			buf.Reset()
		default:
			buf.WriteRune(char)
		}
	}

	return tree, nil
}

func formatQuery(query string) (string, error) {
	if len(query) == 0 {
		return "", ErrWrongGQLFormat
	}

	query = strings.Replace(query, "}", " }", -1)

	query, err := deleteDoubleSpaces(query)
	if err != nil {
		return "", err
	}

	if query[0] != openComma || query[len(query)-1] != closeComma {
		return "", ErrWrongGQLFormat
	}

	query = strings.Replace(query, "{ ", "{", -1)
	query = strings.Replace(query, " {", "{", -1)
	query = strings.Replace(query, "} ", "}", -1)
	query = strings.Trim(query, "{}")

	return query, nil
}

func deleteDoubleSpaces(str string) (string, error) {
	str = strings.TrimSpace(str)
	str = spacesRegEx.ReplaceAllString(str, " ")

	return str, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package sh

import (
	"bufio"
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"
	"unicode/utf8"
)

const (
	_ = -iota
	EOF
	STRING
)

func parse(r io.Reader, name string) error {
	p := &parser{
		r:    bufio.NewReader(r),
		name: name,
		line: 1,
		col:  0,
	}
	p.next()
	p.program()
	return p.err
}

type parser struct {
	r   *bufio.Reader
	err error

	tok int32
	val string

	name string
	line int
	col  int
}

var reserved = map[rune]bool{
	'\n': true,
	'#':  true,
	'=':  true,
	'&':  true,
	'>':  true,
	'<':  true,
	'|':  true,
	';':  true,
	'(':  true,
	')':  true,
	'{':  true,
	'}':  true,
	'$':  true,
}

var quote = map[rune]bool{
	'"':  true,
	'\'': true,
}

var space = map[rune]bool{
	' ':  true,
	'\t': true,
}

var (
	ident = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
	num   = regexp.MustCompile(`^[1-9][0-9]*$`)
)

func (p *parser) next() {
	r := ' '
	var err error
	for space[r] {
		r, _, err = p.r.ReadRune()
		if err == io.EOF {
			p.tok = EOF
			return
		}
		if err != nil {
			p.errPass(err)
			return
		}
		p.col++
	}
	if r == '\\' {
		p.next()
		if p.got('\n') {
			return
		}
		if err := p.r.UnreadRune(); err != nil {
			p.errPass(err)
			return
		}
		p.col--
	}
	if reserved[r] {
		switch r {
		case '#':
			p.discardUpTo('\n')
			p.next()
			return
		case '$':
			p.next()
			if p.got('{') {
				p.discardUpTo('}')
				p.tok = STRING
				return
			}
		case '\n':
			p.line++
			p.col = 0
			p.tok = '\n'
			return
		default:
			p.tok = r
			return
		}
	}
	if quote[r] {
		p.strContent(byte(r))
		if p.tok == EOF {
			return
		}
		p.tok = STRING
		return
	}
	rs := []rune{r}
	for !reserved[r] && !quote[r] && !space[r] {
		r, _, err = p.r.ReadRune()
		if err == io.EOF {
			break
		}
		if err != nil {
			p.errPass(err)
			return
		}
		p.col++
		rs = append(rs, r)
	}
	if err != io.EOF && len(rs) > 1 {
		if err := p.r.UnreadRune(); err != nil {
			p.errPass(err)
			return
		}
		p.col--
		rs = rs[:len(rs)-1]
	}
	p.tok = STRING
	p.val = string(rs)
	return
}

func (p *parser) strContent(delim byte) {
	v := []string{string(delim)}
	for {
		s, err := p.r.ReadString(delim)
		if err == io.EOF {
			p.tok = EOF
			p.errWanted(rune(delim))
		} else if err != nil {
			p.errPass(err)
		}
		v = append(v, s)
		if delim == '\'' {
			break
		}
		if len(s) > 1 && s[len(s)-2] == '\\' && s[len(s)-1] == delim {
			continue
		}
		break
	}
	p.val = strings.Join(v, "")
	for _, r := range p.val {
		if r == '\n' {
			p.line++
			p.col = 0
		} else {
			p.col++
		}
	}
}

func (p *parser) discardUpTo(delim byte) {
	b, err := p.r.ReadBytes(delim)
	if err == io.EOF {
		p.tok = EOF
	} else if err != nil {
		p.errPass(err)
	}
	p.col += utf8.RuneCount(b)
}

func (p *parser) got(tok int32) bool {
	if p.tok == tok {
		p.next()
		return true
	}
	return false
}

func (p *parser) gotStr(s string) bool {
	if p.tok == STRING && p.val == s {
		p.next()
		return true
	}
	return false
}

func (p *parser) want(tok int32) {
	if p.tok != tok {
		p.errWanted(tok)
		return
	}
	p.next()
}

func (p *parser) wantStr(s string) {
	if p.tok != STRING || p.val != s {
		p.errWantedStr(s)
		return
	}
	p.next()
}

func tokStr(tok int32) string {
	switch tok {
	case 0, EOF:
		return "EOF"
	case STRING:
		return "string"
	default:
		return strconv.QuoteRune(tok)
	}
}

func (p *parser) errPass(err error) {
	if p.err == nil {
		p.err = err
	}
	p.tok = EOF
}

func (p *parser) lineErr(format string, v ...interface{}) {
	var pos string
	if p.name != "" {
		pos = fmt.Sprintf("%s:%d:%d: ", p.name, p.line, p.col)
	} else {
		pos = fmt.Sprintf("%d:%d: ", p.line, p.col)
	}
	p.errPass(fmt.Errorf(pos+format, v...))
}

func (p *parser) errUnexpected() {
	p.lineErr("unexpected token %s", tokStr(p.tok))
}

func (p *parser) errWantedStr(s string) {
	p.lineErr("unexpected token %s, wanted %s", tokStr(p.tok), s)
}

func (p *parser) errWanted(tok int32) {
	p.errWantedStr(tokStr(tok))
}

func (p *parser) errAfterStr(s string) {
	p.lineErr("unexpected token %s after %s", tokStr(p.tok), s)
}

func (p *parser) program() {
	for p.tok != EOF {
		if p.got('\n') {
			continue
		}
		p.command()
	}
}

func (p *parser) command() {
	switch {
	case p.got('('):
		count := 0
		for p.tok != EOF && p.tok != ')' {
			if p.got('\n') {
				continue
			}
			p.command()
			count++
		}
		if count == 0 {
			p.errWantedStr("command")
		}
		p.want(')')
	case p.gotStr("if"):
		p.command()
		p.wantStr("then")
		for p.tok != EOF {
			if p.tok == STRING && (p.val == "fi" || p.val == "else") {
				break
			}
			if p.got('\n') {
				continue
			}
			p.command()
		}
		if p.gotStr("else") {
			for p.tok != EOF {
				if p.tok == STRING && p.val == "fi" {
					break
				}
				if p.got('\n') {
					continue
				}
				p.command()
			}
		}
		p.wantStr("fi")
	case p.gotStr("while"):
		p.command()
		p.wantStr("do")
		for p.tok != EOF {
			if p.tok == STRING && p.val == "done" {
				break
			}
			if p.got('\n') {
				continue
			}
			p.command()
		}
		p.wantStr("done")
	case p.got(STRING):
		for p.tok != EOF {
			lval := p.val
			switch {
			case p.got(STRING):
			case p.got('='):
				if !ident.MatchString(lval) {
					p.col -= utf8.RuneCountInString(lval)
					p.col--
					p.lineErr("invalid var name %q", lval)
					return
				}
				p.got(STRING)
			case p.got('&'):
				if p.got('&') {
					p.command()
				}
				return
			case p.got('|'):
				p.got('|')
				p.command()
				return
			case p.got('('):
				if !ident.MatchString(lval) {
					p.col -= utf8.RuneCountInString(lval)
					p.col--
					p.lineErr("invalid func name %q", lval)
					return
				}
				p.want(')')
				p.command()
				return
			case p.got('>'):
				p.redirectDest()
			case p.got('<'):
				p.want(STRING)
			case p.got(';'):
				return
			case p.got('\n'):
				return
			default:
				p.errAfterStr("command")
			}
		}
	case p.got('{'):
		for p.tok != EOF && p.tok != '}' {
			if p.got('\n') {
				continue
			}
			p.command()
		}
		p.want('}')
		switch {
		case p.got('&'):
			if p.got('&') {
				p.command()
			}
			return
		case p.got('|'):
			p.got('|')
			p.command()
			return
		case p.got('>'):
			p.redirectDest()
		case p.got('<'):
			p.want(STRING)
		case p.got(';'):
			return
		case p.got('\n'):
			return
		default:
			p.errAfterStr("block")
		}
	default:
		p.errWantedStr("command")
	}
}

func (p *parser) redirectDest() {
	switch {
	case p.got('&'):
		p.want(STRING)
		if !num.MatchString(p.val) {
			p.errWantedStr("number")
		}
		return
	case p.got('>'):
	}
	p.want(STRING)
}
<commit_msg>Use a map to stringify tokens<commit_after>// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package sh

import (
	"bufio"
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"
	"unicode/utf8"
)

const (
	_ = -iota
	EOF
	STRING
)

func parse(r io.Reader, name string) error {
	p := &parser{
		r:    bufio.NewReader(r),
		name: name,
		line: 1,
		col:  0,
	}
	p.next()
	p.program()
	return p.err
}

type parser struct {
	r   *bufio.Reader
	err error

	tok int32
	val string

	name string
	line int
	col  int
}

var reserved = map[rune]bool{
	'\n': true,
	'#':  true,
	'=':  true,
	'&':  true,
	'>':  true,
	'<':  true,
	'|':  true,
	';':  true,
	'(':  true,
	')':  true,
	'{':  true,
	'}':  true,
	'$':  true,
}

var quote = map[rune]bool{
	'"':  true,
	'\'': true,
}

var space = map[rune]bool{
	' ':  true,
	'\t': true,
}

var (
	ident = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
	num   = regexp.MustCompile(`^[1-9][0-9]*$`)
)

func (p *parser) next() {
	r := ' '
	var err error
	for space[r] {
		r, _, err = p.r.ReadRune()
		if err == io.EOF {
			p.tok = EOF
			return
		}
		if err != nil {
			p.errPass(err)
			return
		}
		p.col++
	}
	if r == '\\' {
		p.next()
		if p.got('\n') {
			return
		}
		if err := p.r.UnreadRune(); err != nil {
			p.errPass(err)
			return
		}
		p.col--
	}
	if reserved[r] {
		switch r {
		case '#':
			p.discardUpTo('\n')
			p.next()
			return
		case '$':
			p.next()
			if p.got('{') {
				p.discardUpTo('}')
				p.tok = STRING
				return
			}
		case '\n':
			p.line++
			p.col = 0
			p.tok = '\n'
			return
		default:
			p.tok = r
			return
		}
	}
	if quote[r] {
		p.strContent(byte(r))
		if p.tok == EOF {
			return
		}
		p.tok = STRING
		return
	}
	rs := []rune{r}
	for !reserved[r] && !quote[r] && !space[r] {
		r, _, err = p.r.ReadRune()
		if err == io.EOF {
			break
		}
		if err != nil {
			p.errPass(err)
			return
		}
		p.col++
		rs = append(rs, r)
	}
	if err != io.EOF && len(rs) > 1 {
		if err := p.r.UnreadRune(); err != nil {
			p.errPass(err)
			return
		}
		p.col--
		rs = rs[:len(rs)-1]
	}
	p.tok = STRING
	p.val = string(rs)
	return
}

func (p *parser) strContent(delim byte) {
	v := []string{string(delim)}
	for {
		s, err := p.r.ReadString(delim)
		if err == io.EOF {
			p.tok = EOF
			p.errWanted(rune(delim))
		} else if err != nil {
			p.errPass(err)
		}
		v = append(v, s)
		if delim == '\'' {
			break
		}
		if len(s) > 1 && s[len(s)-2] == '\\' && s[len(s)-1] == delim {
			continue
		}
		break
	}
	p.val = strings.Join(v, "")
	for _, r := range p.val {
		if r == '\n' {
			p.line++
			p.col = 0
		} else {
			p.col++
		}
	}
}

func (p *parser) discardUpTo(delim byte) {
	b, err := p.r.ReadBytes(delim)
	if err == io.EOF {
		p.tok = EOF
	} else if err != nil {
		p.errPass(err)
	}
	p.col += utf8.RuneCount(b)
}

func (p *parser) got(tok int32) bool {
	if p.tok == tok {
		p.next()
		return true
	}
	return false
}

func (p *parser) gotStr(s string) bool {
	if p.tok == STRING && p.val == s {
		p.next()
		return true
	}
	return false
}

func (p *parser) want(tok int32) {
	if p.tok != tok {
		p.errWanted(tok)
		return
	}
	p.next()
}

func (p *parser) wantStr(s string) {
	if p.tok != STRING || p.val != s {
		p.errWantedStr(s)
		return
	}
	p.next()
}

var tokStrs = map[int32]string{
	0:      "EOF",
	EOF:    "EOF",
	STRING: "string",
}

func tokStr(tok int32) string {
	if s, e := tokStrs[tok]; e {
		return s
	}
	return strconv.QuoteRune(tok)
}

func (p *parser) errPass(err error) {
	if p.err == nil {
		p.err = err
	}
	p.tok = EOF
}

func (p *parser) lineErr(format string, v ...interface{}) {
	var pos string
	if p.name != "" {
		pos = fmt.Sprintf("%s:%d:%d: ", p.name, p.line, p.col)
	} else {
		pos = fmt.Sprintf("%d:%d: ", p.line, p.col)
	}
	p.errPass(fmt.Errorf(pos+format, v...))
}

func (p *parser) errUnexpected() {
	p.lineErr("unexpected token %s", tokStr(p.tok))
}

func (p *parser) errWantedStr(s string) {
	p.lineErr("unexpected token %s, wanted %s", tokStr(p.tok), s)
}

func (p *parser) errWanted(tok int32) {
	p.errWantedStr(tokStr(tok))
}

func (p *parser) errAfterStr(s string) {
	p.lineErr("unexpected token %s after %s", tokStr(p.tok), s)
}

func (p *parser) program() {
	for p.tok != EOF {
		if p.got('\n') {
			continue
		}
		p.command()
	}
}

func (p *parser) command() {
	switch {
	case p.got('('):
		count := 0
		for p.tok != EOF && p.tok != ')' {
			if p.got('\n') {
				continue
			}
			p.command()
			count++
		}
		if count == 0 {
			p.errWantedStr("command")
		}
		p.want(')')
	case p.gotStr("if"):
		p.command()
		p.wantStr("then")
		for p.tok != EOF {
			if p.tok == STRING && (p.val == "fi" || p.val == "else") {
				break
			}
			if p.got('\n') {
				continue
			}
			p.command()
		}
		if p.gotStr("else") {
			for p.tok != EOF {
				if p.tok == STRING && p.val == "fi" {
					break
				}
				if p.got('\n') {
					continue
				}
				p.command()
			}
		}
		p.wantStr("fi")
	case p.gotStr("while"):
		p.command()
		p.wantStr("do")
		for p.tok != EOF {
			if p.tok == STRING && p.val == "done" {
				break
			}
			if p.got('\n') {
				continue
			}
			p.command()
		}
		p.wantStr("done")
	case p.got(STRING):
		for p.tok != EOF {
			lval := p.val
			switch {
			case p.got(STRING):
			case p.got('='):
				if !ident.MatchString(lval) {
					p.col -= utf8.RuneCountInString(lval)
					p.col--
					p.lineErr("invalid var name %q", lval)
					return
				}
				p.got(STRING)
			case p.got('&'):
				if p.got('&') {
					p.command()
				}
				return
			case p.got('|'):
				p.got('|')
				p.command()
				return
			case p.got('('):
				if !ident.MatchString(lval) {
					p.col -= utf8.RuneCountInString(lval)
					p.col--
					p.lineErr("invalid func name %q", lval)
					return
				}
				p.want(')')
				p.command()
				return
			case p.got('>'):
				p.redirectDest()
			case p.got('<'):
				p.want(STRING)
			case p.got(';'):
				return
			case p.got('\n'):
				return
			default:
				p.errAfterStr("command")
			}
		}
	case p.got('{'):
		for p.tok != EOF && p.tok != '}' {
			if p.got('\n') {
				continue
			}
			p.command()
		}
		p.want('}')
		switch {
		case p.got('&'):
			if p.got('&') {
				p.command()
			}
			return
		case p.got('|'):
			p.got('|')
			p.command()
			return
		case p.got('>'):
			p.redirectDest()
		case p.got('<'):
			p.want(STRING)
		case p.got(';'):
			return
		case p.got('\n'):
			return
		default:
			p.errAfterStr("block")
		}
	default:
		p.errWantedStr("command")
	}
}

func (p *parser) redirectDest() {
	switch {
	case p.got('&'):
		p.want(STRING)
		if !num.MatchString(p.val) {
			p.errWantedStr("number")
		}
		return
	case p.got('>'):
	}
	p.want(STRING)
}
<|endoftext|>


<commit_before>package nsf

type Apu struct {
	S1, S2 Square

	Odd        bool
	FC         byte
	FT         byte
	IrqDisable bool
}

type Square struct {
	Envelope
	Timer
	Length
	Sweep
	Duty

	Enable bool
}

type Duty struct {
	Type    byte
	Counter byte
}

type Sweep struct {
	Shift     byte
	Negate    bool
	Period    byte
	Enable    bool
	Divider   byte
	Reset     bool
	NegOffset int
}

type Envelope struct {
	Volume   byte
	Divider  byte
	Counter  byte
	Loop     bool
	Constant bool
	Start    bool
}

type Timer struct {
	Tick   uint16
	Length uint16
}

type Length struct {
	Halt    bool
	Counter byte
}

func (a *Apu) Init() {
	a.S1.Sweep.NegOffset = -1
	for i := uint16(0x4000); i <= 0x400f; i++ {
		a.Write(i, 0)
	}
	a.Write(0x4010, 0x10)
	a.Write(0x4011, 0)
	a.Write(0x4012, 0)
	a.Write(0x4013, 0)
	a.Write(0x4015, 0xf)
	a.Write(0x4017, 0)
}

func (a *Apu) Write(v uint16, b byte) {
	switch v & 0xff {
	case 0x00:
		a.S1.Control1(b)
	case 0x01:
		a.S1.Control2(b)
	case 0x02:
		a.S1.Control3(b)
	case 0x03:
		a.S1.Control4(b)
	case 0x04:
		a.S2.Control1(b)
	case 0x05:
		a.S2.Control2(b)
	case 0x06:
		a.S2.Control3(b)
	case 0x07:
		a.S2.Control4(b)
	case 0x15:
		a.S1.Disable(b&0x1 == 0)
		a.S2.Disable(b&0x2 == 0)
	case 0x17:
		a.FT = 0
		if b&0x80 != 0 {
			a.FC = 5
			a.FrameStep()
		} else {
			a.FC = 4
		}
		a.IrqDisable = b&0x40 != 0
	}
}

func (s *Square) Control1(b byte) {
	s.Envelope.Control(b)
	s.Duty.Control(b)
	s.Length.Halt = b&0x20 != 0
}

func (s *Square) Control2(b byte) {
	s.Sweep.Control(b)
}

func (s *Square) Control3(b byte) {
	s.Timer.Length &= 0xff00
	s.Timer.Length |= uint16(b)
}

func (s *Square) Control4(b byte) {
	s.Timer.Length &= 0xff
	s.Timer.Length |= uint16(b&0x7) << 8
	s.Length.Set(b >> 3)

	s.Envelope.Start = true
	s.Duty.Counter = 0
}

func (d *Duty) Control(b byte) {
	d.Type = b >> 6
}

func (s *Sweep) Control(b byte) {
	s.Shift = b & 0x7
	s.Negate = b&0x8 != 0
	s.Period = (b >> 4) & 0x7
	s.Enable = b&0x80 != 0
	s.Reset = true
}

func (e *Envelope) Control(b byte) {
	e.Volume = b & 0xf
	e.Constant = b&0x10 != 0
	e.Loop = b&0x20 != 0
}

func (l *Length) Set(b byte) {
	if !l.Halt {
		l.Counter = LenLookup[b]
	}
}

func (l *Length) Enabled() bool {
	return l.Counter != 0
}

func (s *Square) Disable(b bool) {
	s.Enable = !b
	if b {
		s.Length.Counter = 0
	}
}

func (a *Apu) Read(v uint16) byte {
	var b byte
	if v == 0x4015 {
		if a.S1.Length.Counter > 0 {
			b |= 0x1
		}
		if a.S2.Length.Counter > 0 {
			b |= 0x2
		}
	}
	return b
}

func (d *Duty) Clock() {
	if d.Counter == 0 {
		d.Counter = 7
	} else {
		d.Counter--
	}
}

func (s *Sweep) Clock() (r bool) {
	if s.Divider == 0 {
		s.Divider = s.Period
		r = true
	} else {
		s.Divider--
	}
	if s.Reset {
		s.Divider = 0
		s.Reset = false
	}
	return
}

func (e *Envelope) Clock() {
	if e.Start {
		e.Start = false
		e.Counter = 15
	} else {
		if e.Divider == 0 {
			e.Divider = e.Volume
			if e.Counter != 0 {
				e.Counter--
			} else if e.Loop {
				e.Counter = 15
			}
		} else {
			e.Divider--
		}
	}
}

// 1.79 MHz/(N+1)
// square: -> duty cycle generator
// triangle: -> triangle step generator
// noise: -> random number generator
func (t *Timer) Clock() bool {
	if t.Tick == 0 {
		t.Tick = t.Length
	} else {
		t.Tick--
	}
	return t.Tick == t.Length
}

func (s *Square) Clock() {
	if s.Timer.Clock() {
		s.Duty.Clock()
	}
}

func (a *Apu) Step() {
	if a.Odd {
		if a.S1.Enable {
			a.S1.Clock()
		}
		if a.S2.Enable {
			a.S2.Clock()
		}
	}
	a.Odd = !a.Odd
	}
}

func (a *Apu) FrameStep() {
	a.FT++
	if a.FT == a.FC {
		a.FT = 0
	}
	if a.FT <= 3 {
		a.S1.Envelope.Clock()
	}
	if a.FT == 1 || a.FT == 3 {
		a.S1.FrameStep()
		a.S2.FrameStep()
	}
	if a.FC == 4 && a.FT == 3 && !a.IrqDisable {
		// todo: assert cpu irq line
	}
}

func (s *Square) FrameStep() {
	s.Length.Clock()
	if s.Sweep.Clock() && s.Sweep.Enable && s.Sweep.Shift > 0 {
		r := s.SweepResult()
		if r <= 0x7ff {
			s.Timer.Tick = r
		}
	}
}

func (l *Length) Clock() {
	if !l.Halt && l.Counter > 0 {
		l.Counter--
	}
}

func (a *Apu) Volume() float32 {
	p := PulseOut[a.S1.Volume()+a.S2.Volume()]
	return p
}

func (s *Square) Volume() uint8 {
	if s.Enable && s.Duty.Enabled() && s.Length.Enabled() && s.Timer.Tick >= 8 && s.SweepResult() <= 0x7ff {
		return s.Envelope.Output()
	}
	return 0
}

func (e *Envelope) Output() byte {
	if e.Constant {
		return e.Volume
	}
	return e.Counter
}

func (s *Square) SweepResult() uint16 {
	r := int(s.Timer.Tick >> s.Sweep.Shift)
	if s.Sweep.Negate {
		r =  - r
	}
	r += int(s.Timer.Tick)
	if r > 0x7ff {
		r = 0x800
	}
	return uint16(r)
}

func (d *Duty) Enabled() bool {
	return DutyCycle[d.Type][d.Counter] == 1
}

var (
	PulseOut  [32]float32
	DutyCycle = [4][8]byte{
		{0, 1, 0, 0, 0, 0, 0, 0},
		{0, 1, 1, 0, 0, 0, 0, 0},
		{0, 1, 1, 1, 1, 0, 0, 0},
		{1, 0, 0, 1, 1, 1, 1, 1},
	}
	LenLookup = []byte{
		0x0a, 0xfe, 0x14, 0x02,
		0x28, 0x04, 0x50, 0x06,
		0xa0, 0x08, 0x3c, 0x0a,
		0x0e, 0x0c, 0x1a, 0x0e,
		0x0c, 0x10, 0x18, 0x12,
		0x30, 0x14, 0x60, 0x16,
		0xc0, 0x18, 0x48, 0x1a,
		0x10, 0x1c, 0x20, 0x1e,
	}
)

func init() {
	for i := range PulseOut {
		PulseOut[i] = 95.88 / (8128/float32(i) + 100)
	}
}
<commit_msg>Remove comment<commit_after>package nsf

type Apu struct {
	S1, S2 Square

	Odd        bool
	FC         byte
	FT         byte
	IrqDisable bool
}

type Square struct {
	Envelope
	Timer
	Length
	Sweep
	Duty

	Enable bool
}

type Duty struct {
	Type    byte
	Counter byte
}

type Sweep struct {
	Shift     byte
	Negate    bool
	Period    byte
	Enable    bool
	Divider   byte
	Reset     bool
	NegOffset int
}

type Envelope struct {
	Volume   byte
	Divider  byte
	Counter  byte
	Loop     bool
	Constant bool
	Start    bool
}

type Timer struct {
	Tick   uint16
	Length uint16
}

type Length struct {
	Halt    bool
	Counter byte
}

func (a *Apu) Init() {
	a.S1.Sweep.NegOffset = -1
	for i := uint16(0x4000); i <= 0x400f; i++ {
		a.Write(i, 0)
	}
	a.Write(0x4010, 0x10)
	a.Write(0x4011, 0)
	a.Write(0x4012, 0)
	a.Write(0x4013, 0)
	a.Write(0x4015, 0xf)
	a.Write(0x4017, 0)
}

func (a *Apu) Write(v uint16, b byte) {
	switch v & 0xff {
	case 0x00:
		a.S1.Control1(b)
	case 0x01:
		a.S1.Control2(b)
	case 0x02:
		a.S1.Control3(b)
	case 0x03:
		a.S1.Control4(b)
	case 0x04:
		a.S2.Control1(b)
	case 0x05:
		a.S2.Control2(b)
	case 0x06:
		a.S2.Control3(b)
	case 0x07:
		a.S2.Control4(b)
	case 0x15:
		a.S1.Disable(b&0x1 == 0)
		a.S2.Disable(b&0x2 == 0)
	case 0x17:
		a.FT = 0
		if b&0x80 != 0 {
			a.FC = 5
			a.FrameStep()
		} else {
			a.FC = 4
		}
		a.IrqDisable = b&0x40 != 0
	}
}

func (s *Square) Control1(b byte) {
	s.Envelope.Control(b)
	s.Duty.Control(b)
	s.Length.Halt = b&0x20 != 0
}

func (s *Square) Control2(b byte) {
	s.Sweep.Control(b)
}

func (s *Square) Control3(b byte) {
	s.Timer.Length &= 0xff00
	s.Timer.Length |= uint16(b)
}

func (s *Square) Control4(b byte) {
	s.Timer.Length &= 0xff
	s.Timer.Length |= uint16(b&0x7) << 8
	s.Length.Set(b >> 3)

	s.Envelope.Start = true
	s.Duty.Counter = 0
}

func (d *Duty) Control(b byte) {
	d.Type = b >> 6
}

func (s *Sweep) Control(b byte) {
	s.Shift = b & 0x7
	s.Negate = b&0x8 != 0
	s.Period = (b >> 4) & 0x7
	s.Enable = b&0x80 != 0
	s.Reset = true
}

func (e *Envelope) Control(b byte) {
	e.Volume = b & 0xf
	e.Constant = b&0x10 != 0
	e.Loop = b&0x20 != 0
}

func (l *Length) Set(b byte) {
	if !l.Halt {
		l.Counter = LenLookup[b]
	}
}

func (l *Length) Enabled() bool {
	return l.Counter != 0
}

func (s *Square) Disable(b bool) {
	s.Enable = !b
	if b {
		s.Length.Counter = 0
	}
}

func (a *Apu) Read(v uint16) byte {
	var b byte
	if v == 0x4015 {
		if a.S1.Length.Counter > 0 {
			b |= 0x1
		}
		if a.S2.Length.Counter > 0 {
			b |= 0x2
		}
	}
	return b
}

func (d *Duty) Clock() {
	if d.Counter == 0 {
		d.Counter = 7
	} else {
		d.Counter--
	}
}

func (s *Sweep) Clock() (r bool) {
	if s.Divider == 0 {
		s.Divider = s.Period
		r = true
	} else {
		s.Divider--
	}
	if s.Reset {
		s.Divider = 0
		s.Reset = false
	}
	return
}

func (e *Envelope) Clock() {
	if e.Start {
		e.Start = false
		e.Counter = 15
	} else {
		if e.Divider == 0 {
			e.Divider = e.Volume
			if e.Counter != 0 {
				e.Counter--
			} else if e.Loop {
				e.Counter = 15
			}
		} else {
			e.Divider--
		}
	}
}

func (t *Timer) Clock() bool {
	if t.Tick == 0 {
		t.Tick = t.Length
	} else {
		t.Tick--
	}
	return t.Tick == t.Length
}

func (s *Square) Clock() {
	if s.Timer.Clock() {
		s.Duty.Clock()
	}
}

func (a *Apu) Step() {
	if a.Odd {
		if a.S1.Enable {
			a.S1.Clock()
		}
		if a.S2.Enable {
			a.S2.Clock()
		}
	}
	a.Odd = !a.Odd
	}
}

func (a *Apu) FrameStep() {
	a.FT++
	if a.FT == a.FC {
		a.FT = 0
	}
	if a.FT <= 3 {
		a.S1.Envelope.Clock()
	}
	if a.FT == 1 || a.FT == 3 {
		a.S1.FrameStep()
		a.S2.FrameStep()
	}
	if a.FC == 4 && a.FT == 3 && !a.IrqDisable {
		// todo: assert cpu irq line
	}
}

func (s *Square) FrameStep() {
	s.Length.Clock()
	if s.Sweep.Clock() && s.Sweep.Enable && s.Sweep.Shift > 0 {
		r := s.SweepResult()
		if r <= 0x7ff {
			s.Timer.Tick = r
		}
	}
}

func (l *Length) Clock() {
	if !l.Halt && l.Counter > 0 {
		l.Counter--
	}
}

func (a *Apu) Volume() float32 {
	p := PulseOut[a.S1.Volume()+a.S2.Volume()]
	return p
}

func (s *Square) Volume() uint8 {
	if s.Enable && s.Duty.Enabled() && s.Length.Enabled() && s.Timer.Tick >= 8 && s.SweepResult() <= 0x7ff {
		return s.Envelope.Output()
	}
	return 0
}

func (e *Envelope) Output() byte {
	if e.Constant {
		return e.Volume
	}
	return e.Counter
}

func (s *Square) SweepResult() uint16 {
	r := int(s.Timer.Tick >> s.Sweep.Shift)
	if s.Sweep.Negate {
		r =  - r
	}
	r += int(s.Timer.Tick)
	if r > 0x7ff {
		r = 0x800
	}
	return uint16(r)
}

func (d *Duty) Enabled() bool {
	return DutyCycle[d.Type][d.Counter] == 1
}

var (
	PulseOut  [32]float32
	DutyCycle = [4][8]byte{
		{0, 1, 0, 0, 0, 0, 0, 0},
		{0, 1, 1, 0, 0, 0, 0, 0},
		{0, 1, 1, 1, 1, 0, 0, 0},
		{1, 0, 0, 1, 1, 1, 1, 1},
	}
	LenLookup = []byte{
		0x0a, 0xfe, 0x14, 0x02,
		0x28, 0x04, 0x50, 0x06,
		0xa0, 0x08, 0x3c, 0x0a,
		0x0e, 0x0c, 0x1a, 0x0e,
		0x0c, 0x10, 0x18, 0x12,
		0x30, 0x14, 0x60, 0x16,
		0xc0, 0x18, 0x48, 0x1a,
		0x10, 0x1c, 0x20, 0x1e,
	}
)

func init() {
	for i := range PulseOut {
		PulseOut[i] = 95.88 / (8128/float32(i) + 100)
	}
}
<|endoftext|>


<commit_before>package xmaintnote

import (
	"fmt"
	"io"

	"github.com/jda/ical"
)

type MaintNote struct {
}

type MaintEvent struct {
	Summary       string
	Start         string
	End           string
	Created       string
	UID           string
	Sequence      int
	Provider      string
	Account       string
	MaintenanceID string
	ObjectID      string // CircuitID
	Impact        string
	Status        string
}

// NewMaintNote creates a new MaintNote instance
func NewMaintNote() *MaintNote {
	mn := MaintNote{}
	return &mn
}

// ParseMaintNote parses a Maintenence Notification from a reader
func ParseMaintNote(r io.Reader) (mn *MaintNote, err error) {
	err = parseIcal(r)
	return nil, err
}

func parseIcal(r io.Reader) error {
	calendar, err := ical.Parse(r)
	if err != nil {
		return err
	}

	fmt.Printf("Cal: %+v\n", calendar)
	printProp(calendar.Properties)
	printEvent(calendar.Events)
	return nil
}

func printProp(props []*ical.Property) {
	for p := range props {
		fmt.Printf("\tGot prop: %+v\n", props[p])
	}
}

func printEvent(events []*ical.Event) {
	for e := range events {
		fmt.Println("events!")
		printProp(events[e].Properties)
	}
}

// ValidStatus checks if a status value is a valid X-MAINTNOTE status
func ValidStatus(status string) bool {
	if status == StatusTenative {
		return true
	}

	if status == StatusCancelled {
		return true
	}

	if status == StatusInProcess {
		return true
	}

	if status == StatusCompleted {
		return true
	}

	return false
}

// ValidImpact checks if a status value is a valid X-MAINTNOTE impact
func ValidImpact(impact string) bool {
	if impact == ImpactNone {
		return true
	}

	if impact == ImpactReducedRedundancy {
		return true
	}

	if impact == ImpactDegraded {
		return true
	}

	if impact == ImpactOutage {
		return true
	}

	return false
}
<commit_msg>Switch ical library because license<commit_after>package xmaintnote

import (
	"fmt"
	"io"

	"github.com/luxifer/ical"
)

type MaintNote struct {
}

type MaintEvent struct {
	Summary       string
	Start         string
	End           string
	Created       string
	UID           string
	Sequence      int
	Provider      string
	Account       string
	MaintenanceID string
	ObjectID      string // CircuitID
	Impact        string
	Status        string
}

// NewMaintNote creates a new MaintNote instance
func NewMaintNote() *MaintNote {
	mn := MaintNote{}
	return &mn
}

// ParseMaintNote parses a Maintenence Notification from a reader
func ParseMaintNote(r io.Reader) (mn *MaintNote, err error) {
	err = parseIcal(r)
	return nil, err
}

func parseIcal(r io.Reader) error {
	calendar, err := ical.Parse(r)
	if err != nil {
		return err
	}

	fmt.Printf("Cal: %+v\n", calendar)
	printProp(calendar.Properties)
	printEvent(calendar.Events)
	return nil
}

func printProp(props []*ical.Property) {
	for p := range props {
		fmt.Printf("\tGot prop: %+v\n", props[p])
	}
}

func printEvent(events []*ical.Event) {
	for e := range events {
		fmt.Println("events!")
		printProp(events[e].Properties)
	}
}

// ValidStatus checks if a status value is a valid X-MAINTNOTE status
func ValidStatus(status string) bool {
	if status == StatusTenative {
		return true
	}

	if status == StatusCancelled {
		return true
	}

	if status == StatusInProcess {
		return true
	}

	if status == StatusCompleted {
		return true
	}

	return false
}

// ValidImpact checks if a status value is a valid X-MAINTNOTE impact
func ValidImpact(impact string) bool {
	if impact == ImpactNone {
		return true
	}

	if impact == ImpactReducedRedundancy {
		return true
	}

	if impact == ImpactDegraded {
		return true
	}

	if impact == ImpactOutage {
		return true
	}

	return false
}
<|endoftext|>


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

package id3v2

import (
	"errors"
	"io"
	"os"

	"github.com/bogem/id3v2/util"
)

const frameHeaderSize = 10

var errBlankFrame = errors.New("id or size of frame are blank")

type frameHeader struct {
	ID        string
	FrameSize int64
}

func parseTag(file *os.File) (*Tag, error) {
	if file == nil {
		err := errors.New("Invalid file: file is nil")
		return nil, err
	}
	header, err := parseHeader(file)
	if err == errNoTag {
		return newTag(file, 0, 4), nil
	}
	if err != nil {
		err = errors.New("trying to parse tag header: " + err.Error())
		return nil, err
	}
	if header.Version < 3 {
		err = errors.New("unsupported version of ID3 tag")
		return nil, err
	}

	t := newTag(file, tagHeaderSize+header.FramesSize, header.Version)
	err = t.parseAllFrames()

	return t, err
}

func newTag(file *os.File, originalSize int64, version byte) *Tag {
	return &Tag{
		frames:    make(map[string]Framer),
		sequences: make(map[string]sequencer),

		file:         file,
		originalSize: originalSize,
		version:      version,
	}
}

func (t *Tag) parseAllFrames() error {
	// Initial position of read - beginning of first frame
	if _, err := t.file.Seek(tagHeaderSize, os.SEEK_SET); err != nil {
		return err
	}

	size := t.originalSize - tagHeaderSize // Size of all frames = Size of tag - tag header
	fileReader := io.LimitReader(t.file, size)

	for {
		id, frame, err := parseFrame(fileReader)
		if err == io.EOF || err == errBlankFrame || err == util.ErrInvalidSizeFormat {
			break
		}
		if err != nil {
			return err
		}

		t.AddFrame(id, frame)
	}

	return nil
}

var frameBody = new(io.LimitedReader)

func parseFrame(rd io.Reader) (id string, frame Framer, err error) {
	header, err := parseFrameHeader(rd)
	if err != nil {
		return "", nil, err
	}
	id = header.ID

	frameBody.R = rd
	frameBody.N = header.FrameSize

	frame, err = parseFrameBody(id, frameBody)
	return id, frame, err
}

func parseFrameHeader(rd io.Reader) (frameHeader, error) {
	var header frameHeader

	_, err := rd.Read(fhBuf)
	if err != nil {
		return header, err
	}

	id := string(fhBuf[:4])
	frameSize, err := util.ParseSize(fhBuf[4:8])
	if err != nil {
		return header, err
	}

	if id == "" || frameSize == 0 {
		return header, errBlankFrame
	}

	header.ID = id
	header.FrameSize = frameSize
	return header, nil

}

func parseFrameBody(id string, rd io.Reader) (Framer, error) {
	if id[0] == 'T' {
		return parseTextFrame(rd)
	}

	if parseFunc, exists := parsers[id]; exists {
		return parseFunc(rd)
	}

	return parseUnknownFrame(rd)
}

var fhBuf = make([]byte, frameHeaderSize)
<commit_msg>Move fhBuf above parseFrameHeader<commit_after>// Copyright 2016 Albert Nigmatzianov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package id3v2

import (
	"errors"
	"io"
	"os"

	"github.com/bogem/id3v2/util"
)

const frameHeaderSize = 10

var errBlankFrame = errors.New("id or size of frame are blank")

type frameHeader struct {
	ID        string
	FrameSize int64
}

func parseTag(file *os.File) (*Tag, error) {
	if file == nil {
		err := errors.New("Invalid file: file is nil")
		return nil, err
	}
	header, err := parseHeader(file)
	if err == errNoTag {
		return newTag(file, 0, 4), nil
	}
	if err != nil {
		err = errors.New("trying to parse tag header: " + err.Error())
		return nil, err
	}
	if header.Version < 3 {
		err = errors.New("unsupported version of ID3 tag")
		return nil, err
	}

	t := newTag(file, tagHeaderSize+header.FramesSize, header.Version)
	err = t.parseAllFrames()

	return t, err
}

func newTag(file *os.File, originalSize int64, version byte) *Tag {
	return &Tag{
		frames:    make(map[string]Framer),
		sequences: make(map[string]sequencer),

		file:         file,
		originalSize: originalSize,
		version:      version,
	}
}

func (t *Tag) parseAllFrames() error {
	// Initial position of read - beginning of first frame
	if _, err := t.file.Seek(tagHeaderSize, os.SEEK_SET); err != nil {
		return err
	}

	size := t.originalSize - tagHeaderSize // Size of all frames = Size of tag - tag header
	fileReader := io.LimitReader(t.file, size)

	for {
		id, frame, err := parseFrame(fileReader)
		if err == io.EOF || err == errBlankFrame || err == util.ErrInvalidSizeFormat {
			break
		}
		if err != nil {
			return err
		}

		t.AddFrame(id, frame)
	}

	return nil
}

var frameBody = new(io.LimitedReader)

func parseFrame(rd io.Reader) (id string, frame Framer, err error) {
	header, err := parseFrameHeader(rd)
	if err != nil {
		return "", nil, err
	}
	id = header.ID

	frameBody.R = rd
	frameBody.N = header.FrameSize

	frame, err = parseFrameBody(id, frameBody)
	return id, frame, err
}

var fhBuf = make([]byte, frameHeaderSize)

func parseFrameHeader(rd io.Reader) (frameHeader, error) {
	var header frameHeader

	_, err := rd.Read(fhBuf)
	if err != nil {
		return header, err
	}

	id := string(fhBuf[:4])
	frameSize, err := util.ParseSize(fhBuf[4:8])
	if err != nil {
		return header, err
	}

	if id == "" || frameSize == 0 {
		return header, errBlankFrame
	}

	header.ID = id
	header.FrameSize = frameSize
	return header, nil

}

func parseFrameBody(id string, rd io.Reader) (Framer, error) {
	if id[0] == 'T' {
		return parseTextFrame(rd)
	}

	if parseFunc, exists := parsers[id]; exists {
		return parseFunc(rd)
	}

	return parseUnknownFrame(rd)
}
<|endoftext|>


<commit_before>package risk

import (
	"encoding/json"
	"time"
)

const (
	// GetScoresEnpoint location of the getscores endpoint
	GetScoresEnpoint = "v1/score/getScores"

	// EcosystemScope constant with name of scope for ecosystem
	EcosystemScope = "ecosystem"

	// SupplyChainScope constant with name of scope for supply chain
	SupplyChainScope = "supply_chain"

	// TechnologyScope constant with name of scope for technology
	TechnologyScope = "technology"
)

type Metrics struct {
	ID      string   `json:"id"`
	Metrics []Metric `json:"metrics"`
}

type MetricsJson struct {
	ID      string       `json:"id"`
	Metrics []MetricJson `json:"metrics"`
}

type Metric struct {
	Name         string         `json:"name"`
	Bindings     []ScoreBinding `json:"bindings"`
	Severity     string         `json:"severity"`
	SeverityRank int            `json:"severity_rank"`
	Value        string         `json:"value"`
	Type         string         `json:"type"`
}

type MetricJson struct {
	Name         string           `json:"name"`
	Bindings     []ScoreBinding   `json:"bindings"`
	Severity     string           `json:"severity"`
	SeverityRank int              `json:"severity_rank"`
	Value        *json.RawMessage `json:"value"`
	Type         string           `json:"type"`
}

// ScoreBinding a mapping from metric to which scope it falls into.
type ScoreBinding struct {
	Metric    string `json:"metric"`
	Scope     string `json:"scope"`
	Category  string `json:"category"`
	Attribute string `json:"attribute"`
	Source    string `json:"source"`
}

// Scores top level struct for modeling the score tree
type Scores struct {
	Name   string  `json:"name"`
	Value  float64 `json:"value"`
	Scopes []Scope `json:"scopes"`
}

// Scope second tier struct for modeling the score tree
type Scope struct {
	Name       string     `json:"name"`
	Value      float64    `json:"value"`
	Categories []Category `json:"-"`
}

// GetScope returns a Scope value based on the name supplied
func (s *Scores) GetScope(name string) *Scope {
	var scope *Scope
	for _, sco := range s.Scopes {
		if sco.Name == name {
			scope = &sco
			break
		}
	}

	if scope == nil {
		scope = &Scope{Name: name}
	}
	return scope
}

// Category third tier struct for modeling the score tree
type Category struct {
	Name       string      `json:"name"`
	Value      float64     `json:"value"`
	Attributes []Attribute `json:"-"`
}

// Attribute leaf tier struct for modeling the score tree
type Attribute struct {
	Name  string  `json:"name"`
	Value float64 `json:"value"`
}

type RiskTag struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}
type MetricMetadata struct {
	Name           string         `json:"name"`
	Definition     string         `json:"definition"`
	Bindings       []ScoreBinding `json:"bindings"`
	RiskTags       []RiskTag      `json:"risk_tags"`
	RelatedMetrics []string       `json:"related_metrics"`
	GraphYN        bool           `json:"graph_yn"`
}

// MetricPoint defines the data needed for points on a single risk point
type MetricPoint struct {
	Name   string `json:"name" xml:"name"`
	Points int    `json:"points" xml:"points"`
}

// MetricPoints defines the data needed for points on a single risk point
type MetricPoints struct {
	Metrics     []MetricPoint `json:"metrics" xml:"metrics"`
	ProcessedAt time.Time     `json:"processed_at" xml:"processed_at"`
}
<commit_msg>remove metric objects that are local to graphql-server<commit_after>package risk

import (
	"encoding/json"
	"time"
)

const (
	// GetScoresEnpoint location of the getscores endpoint
	GetScoresEnpoint = "v1/score/getScores"

	// EcosystemScope constant with name of scope for ecosystem
	EcosystemScope = "ecosystem"

	// SupplyChainScope constant with name of scope for supply chain
	SupplyChainScope = "supply_chain"

	// TechnologyScope constant with name of scope for technology
	TechnologyScope = "technology"
)

type Metrics struct {
	ID      string   `json:"id"`
	Metrics []Metric `json:"metrics"`
}

type Metric struct {
	Name         string           `json:"name"`
	Bindings     []ScoreBinding   `json:"bindings"`
	Severity     string           `json:"severity"`
	SeverityRank int              `json:"severity_rank"`
	Value        *json.RawMessage `json:"value"`
	Type         string           `json:"type"`
}

// ScoreBinding a mapping from metric to which scope it falls into.
type ScoreBinding struct {
	Metric    string `json:"metric"`
	Scope     string `json:"scope"`
	Category  string `json:"category"`
	Attribute string `json:"attribute"`
	Source    string `json:"source"`
}

// Scores top level struct for modeling the score tree
type Scores struct {
	Name   string  `json:"name"`
	Value  float64 `json:"value"`
	Scopes []Scope `json:"scopes"`
}

// Scope second tier struct for modeling the score tree
type Scope struct {
	Name       string     `json:"name"`
	Value      float64    `json:"value"`
	Categories []Category `json:"-"`
}

// GetScope returns a Scope value based on the name supplied
func (s *Scores) GetScope(name string) *Scope {
	var scope *Scope
	for _, sco := range s.Scopes {
		if sco.Name == name {
			scope = &sco
			break
		}
	}

	if scope == nil {
		scope = &Scope{Name: name}
	}
	return scope
}

// Category third tier struct for modeling the score tree
type Category struct {
	Name       string      `json:"name"`
	Value      float64     `json:"value"`
	Attributes []Attribute `json:"-"`
}

// Attribute leaf tier struct for modeling the score tree
type Attribute struct {
	Name  string  `json:"name"`
	Value float64 `json:"value"`
}

type RiskTag struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}
type MetricMetadata struct {
	Name           string         `json:"name"`
	Definition     string         `json:"definition"`
	Bindings       []ScoreBinding `json:"bindings"`
	RiskTags       []RiskTag      `json:"risk_tags"`
	RelatedMetrics []string       `json:"related_metrics"`
	GraphYN        bool           `json:"graph_yn"`
}

// MetricPoint defines the data needed for points on a single risk point
type MetricPoint struct {
	Name   string `json:"name" xml:"name"`
	Points int    `json:"points" xml:"points"`
}

// MetricPoints defines the data needed for points on a single risk point
type MetricPoints struct {
	Metrics     []MetricPoint `json:"metrics" xml:"metrics"`
	ProcessedAt time.Time     `json:"processed_at" xml:"processed_at"`
}
<|endoftext|>


<commit_before>package jcapi

import (
	"encoding/json"
	"fmt"
	"strconv"
)

type JCUser struct {
	Id               string `json:"_id,omitempty"`
	UserName         string `json:"username,omitempty"`
	FirstName        string `json:"firstname,omitempty"`
	LastName         string `json:"lastname,omitempty"`
	Email            string `json:"email"`
	Password         string `json:"password,omitempty"`
	PasswordDate     string `json:"password_date,omitempty"`
	Activated        bool   `json:"activated"`
	ActivationKey    string `json:"activation_key"`
	ExpiredWarned    bool   `json:"expired_warned"`
	PasswordExpired  bool   `json:"password_expired"`
	Sudo             bool   `json:"sudo"`
	Uid              string `json:"unix_uid"`
	Gid              string `json:"unix_guid"`
	EnableManagedUid bool   `json:"enable_managed_uid"`

	TagIds []string `json:"tags,omitempty"` // the list of tag IDs that this user should be put in

	//
	// For identification as an external user directory source
	//
	ExternallyManaged  bool   `json:"externally_managed"`
	ExternalDN         string `json:"external_dn,omitempty"`
	ExternalSourceType string `json:"external_source_type,omitempty"`

	Tags []JCTag // the list of actual tags the user is in
}

//
// Special request structure for sending activation emails
//
type JCUserEmailRequest struct {
	IsSelectAll bool     `json:"isSelectAll"`
	Models      []JCUser `json:"models"`
}

func UsersToString(users []JCUser) string {
	returnVal := ""

	for _, user := range users {
		returnVal += user.ToString()
	}

	return returnVal
}

func (jcuser JCUser) ToString() string {
	//
	// WARNING: Never output password via this method, it could be logged in clear text
	//
	returnVal := fmt.Sprintf("JCUSER: Id=[%s] - UserName=[%s] - FName/LName=[%s/%s] - Email=[%s] - sudo=[%t] - Uid=%s - Gid=%s - enableManagedUid=%t\n",
		jcuser.Id, jcuser.UserName, jcuser.FirstName, jcuser.LastName,
		jcuser.Email, jcuser.Sudo, jcuser.Uid, jcuser.Gid, jcuser.EnableManagedUid)

	returnVal += fmt.Sprintf("JCUSER: ExternallyManaged=[%t] - ExternalDN=[%s] - ExternalSourceType=[%s]\n",
		jcuser.ExternallyManaged, jcuser.ExternalDN, jcuser.ExternalSourceType)

	returnVal += fmt.Sprintf("JCUSER: PasswordExpired=[%t]\n", jcuser.PasswordExpired)

	for _, tag := range jcuser.Tags {
		returnVal += fmt.Sprintf("\t%s\n", tag.ToString())
	}

	return returnVal
}

func setTagIds(user *JCUser) {
	for idx, _ := range user.Tags {
		user.TagIds = append(user.TagIds, user.Tags[idx].Id)
	}
}

func getJCUserFieldsFromInterface(fields map[string]interface{}, user *JCUser) {
	user.Email = fields["email"].(string)

	if _, exists := fields["firstname"]; exists {
		user.FirstName = fields["firstname"].(string)
	}
	if _, exists := fields["lastname"]; exists {
		user.LastName = fields["lastname"].(string)
	}

	user.UserName = fields["username"].(string)
	user.Id = fields["_id"].(string)

	if _, exists := fields["externally_managed"]; exists {
		user.ExternallyManaged = fields["externally_managed"].(bool)
	} else {
		user.ExternallyManaged = false
	}

	user.Sudo = fields["sudo"].(bool)

	if _, exists := fields["external_dn"]; exists {
		user.ExternalDN = fields["external_dn"].(string)
	}

	if _, exists := fields["external_source_type"]; exists {
		user.ExternalSourceType = fields["external_source_type"].(string)
	}

	// Currently returned as float64, not string (though they are posted as string),
	// defect #96322248...
	if floatVal, ok := fields["unix_uid"].(float64); ok {
		user.Uid = strconv.FormatInt(int64(floatVal), 10)
	}
	if floatVal, ok := fields["unix_guid"].(float64); ok {
		user.Gid = strconv.FormatInt(int64(floatVal), 10)
	}

	if _, exists := fields["enable_managed_uid"]; exists {
		user.EnableManagedUid = fields["enable_managed_uid"].(bool)
	}

	if _, exists := fields["password_expired"]; exists {
		user.PasswordExpired = fields["password_expired"].(bool)
	}

	if _, exists := fields["password_date"]; exists {
		user.PasswordDate = fields["password_date"].(string)
	}
}

func getJCUsersFromInterface(userInt interface{}) []JCUser {

	var returnVal []JCUser

	recMap := userInt.(map[string]interface{})

	results := recMap["results"].([]interface{})

	returnVal = make([]JCUser, len(results))

	for idx, result := range results {
		getJCUserFieldsFromInterface(result.(map[string]interface{}), &returnVal[idx])
	}

	return returnVal
}

// Executes a search by email via the JumpCloud API
func (jc JCAPI) GetSystemUserByEmail(email string, withTags bool) ([]JCUser, JCError) {
	var returnVal []JCUser

	jcUserRec, err := jc.Post("/search/systemusers", jc.emailFilter(email))
	if err != nil {
		return nil, fmt.Errorf("ERROR: Post to JumpCloud failed, err='%s'", err)
	}

	returnVal = getJCUsersFromInterface(jcUserRec)

	if withTags {
		tags, err := jc.GetAllTags()
		if err != nil {
			return nil, fmt.Errorf("ERROR: Could not get tags, err='%s'", err)
		}

		for idx, _ := range returnVal {
			returnVal[idx].AddJCTags(tags)
		}
	}

	return returnVal, nil
}

func (jc JCAPI) GetSystemUserById(userId string, withTags bool) (user JCUser, err JCError) {
	url := fmt.Sprintf("/systemusers/%s", userId)

	retVal, err := jc.Get(url)
	if err != nil {
		err = fmt.Errorf("ERROR: Could not get system user by ID '%s', err='%s'", userId, err)
	}

	if retVal != nil {
		getJCUserFieldsFromInterface(retVal.(map[string]interface{}), &user)

		if withTags {
			// I should be able to use err below as the err return value, but there's
			// a compiler bug here in that it thinks a := of err is shadowed here,
			// even though tags should be the only variable declared with the :=
			tags, err2 := jc.GetAllTags()
			if err != nil {
				err = fmt.Errorf("ERROR: Could not get tags, err='%s'", err2)
				return
			}

			user.AddJCTags(tags)
			setTagIds(&user)
		}
	}

	return
}

func (jc JCAPI) GetSystemUsers(withTags bool) (userList []JCUser, err JCError) {
	var returnVal []JCUser

	for skip := 0; skip == 0 || len(returnVal) == searchLimit; skip += searchSkipInterval {
		url := fmt.Sprintf("/systemusers?sort=username&skip=%d&limit=%d", skip, searchLimit)

		jcUserRec, err2 := jc.Get(url)
		if err != nil {
			return nil, fmt.Errorf("ERROR: Post to JumpCloud failed, err='%s'", err2)
		}

		if jcUserRec == nil {
			return nil, fmt.Errorf("ERROR: No users found")
		}

		// We really only care about the ID for the following call...
		returnVal = getJCUsersFromInterface(jcUserRec)

		for i, _ := range returnVal {
			if returnVal[i].Id != "" {

				//
				// Get the rest of the user record, which includes details like
				// the externalDN...
				//
				// We'll get all the tags one time later, so don't get the tags on this call...
				//
				// See above about the compiler error that requires me to use err2 instead of err below...
				//
				detailedUser, err2 := jc.GetSystemUserById(returnVal[i].Id, false)
				if err != nil {
					err = fmt.Errorf("ERROR: Could not get details for user ID '%s', err='%s'", returnVal[i].Id, err2)
					return
				}

				if detailedUser.Id != "" {
					userList = append(userList, detailedUser)
				}
			}
		}
	}

	if withTags {
		tags, err := jc.GetAllTags()
		if err != nil {
			return nil, fmt.Errorf("ERROR: Could not get tags, err='%s'", err)
		}

		for idx, _ := range userList {
			userList[idx].AddJCTags(tags)
			setTagIds(&userList[idx])
		}
	}

	return
}

//
// Resend user email
//
func (jc JCAPI) SendUserActivationEmail(userList []JCUser) (err JCError) {
	for _, user := range userList {
		if user.Id == "" {
			return fmt.Errorf("ERROR: Cannot resend user activation email without a systemuser Id on user ")
		}
	}

	emailRequest := JCUserEmailRequest{
		IsSelectAll: false,
		Models:      userList,
	}

	data, err := json.Marshal(emailRequest)
	if err != nil {
		return fmt.Errorf("ERROR: Could not marshal JCUser object, err='%s'", err)
	}

	url := "/systemusers/reactivate"

	_, err = jc.Do(MapJCOpToHTTP(Insert), url, data)
	if err != nil {
		return fmt.Errorf("ERROR: Could not post resend email request object, err='%s'", err)
	}

	return
}

//
// Add or Update a new user to JumpCloud
//
func (jc JCAPI) AddUpdateUser(op JCOp, user JCUser) (userId string, err JCError) {
	if user.Password != "" {
		user.PasswordDate = getTimeString()
	}

	data, err := json.Marshal(user)
	if err != nil {
		return "", fmt.Errorf("ERROR: Could not marshal JCUser object, err='%s'", err)
	}

	url := "/systemusers"
	if op == Update {
		url += "/" + user.Id
	}

	jcUserRec, err := jc.Do(MapJCOpToHTTP(op), url, data)
	if err != nil {
		return "", fmt.Errorf("ERROR: Could not post new JCUser object, err='%s'", err)
	}

	var returnUser JCUser
	getJCUserFieldsFromInterface(jcUserRec.(map[string]interface{}), &returnUser)

	if returnUser.Email != user.Email {
		return "", fmt.Errorf("ERROR: JumpCloud did not return the same email - this should never happen!")
	}

	userId = returnUser.Id

	return
}

func (jc JCAPI) DeleteUser(user JCUser) JCError {
	_, err := jc.Delete(fmt.Sprintf("/systemusers/%s", user.Id))
	if err != nil {
		return fmt.Errorf("ERROR: Could not delete user '%s': err='%s'", user.Email, err)
	}

	return nil
}
<commit_msg>Fixed a couple of error messages<commit_after>package jcapi

import (
	"encoding/json"
	"fmt"
	"strconv"
)

type JCUser struct {
	Id               string `json:"_id,omitempty"`
	UserName         string `json:"username,omitempty"`
	FirstName        string `json:"firstname,omitempty"`
	LastName         string `json:"lastname,omitempty"`
	Email            string `json:"email"`
	Password         string `json:"password,omitempty"`
	PasswordDate     string `json:"password_date,omitempty"`
	Activated        bool   `json:"activated"`
	ActivationKey    string `json:"activation_key"`
	ExpiredWarned    bool   `json:"expired_warned"`
	PasswordExpired  bool   `json:"password_expired"`
	Sudo             bool   `json:"sudo"`
	Uid              string `json:"unix_uid"`
	Gid              string `json:"unix_guid"`
	EnableManagedUid bool   `json:"enable_managed_uid"`

	TagIds []string `json:"tags,omitempty"` // the list of tag IDs that this user should be put in

	//
	// For identification as an external user directory source
	//
	ExternallyManaged  bool   `json:"externally_managed"`
	ExternalDN         string `json:"external_dn,omitempty"`
	ExternalSourceType string `json:"external_source_type,omitempty"`

	Tags []JCTag // the list of actual tags the user is in
}

//
// Special request structure for sending activation emails
//
type JCUserEmailRequest struct {
	IsSelectAll bool     `json:"isSelectAll"`
	Models      []JCUser `json:"models"`
}

func UsersToString(users []JCUser) string {
	returnVal := ""

	for _, user := range users {
		returnVal += user.ToString()
	}

	return returnVal
}

func (jcuser JCUser) ToString() string {
	//
	// WARNING: Never output password via this method, it could be logged in clear text
	//
	returnVal := fmt.Sprintf("JCUSER: Id=[%s] - UserName=[%s] - FName/LName=[%s/%s] - Email=[%s] - sudo=[%t] - Uid=%s - Gid=%s - enableManagedUid=%t\n",
		jcuser.Id, jcuser.UserName, jcuser.FirstName, jcuser.LastName,
		jcuser.Email, jcuser.Sudo, jcuser.Uid, jcuser.Gid, jcuser.EnableManagedUid)

	returnVal += fmt.Sprintf("JCUSER: ExternallyManaged=[%t] - ExternalDN=[%s] - ExternalSourceType=[%s]\n",
		jcuser.ExternallyManaged, jcuser.ExternalDN, jcuser.ExternalSourceType)

	returnVal += fmt.Sprintf("JCUSER: PasswordExpired=[%t]\n", jcuser.PasswordExpired)

	for _, tag := range jcuser.Tags {
		returnVal += fmt.Sprintf("\t%s\n", tag.ToString())
	}

	return returnVal
}

func setTagIds(user *JCUser) {
	for idx, _ := range user.Tags {
		user.TagIds = append(user.TagIds, user.Tags[idx].Id)
	}
}

func getJCUserFieldsFromInterface(fields map[string]interface{}, user *JCUser) {
	user.Email = fields["email"].(string)

	if _, exists := fields["firstname"]; exists {
		user.FirstName = fields["firstname"].(string)
	}
	if _, exists := fields["lastname"]; exists {
		user.LastName = fields["lastname"].(string)
	}

	user.UserName = fields["username"].(string)
	user.Id = fields["_id"].(string)

	if _, exists := fields["externally_managed"]; exists {
		user.ExternallyManaged = fields["externally_managed"].(bool)
	} else {
		user.ExternallyManaged = false
	}

	user.Sudo = fields["sudo"].(bool)

	if _, exists := fields["external_dn"]; exists {
		user.ExternalDN = fields["external_dn"].(string)
	}

	if _, exists := fields["external_source_type"]; exists {
		user.ExternalSourceType = fields["external_source_type"].(string)
	}

	// Currently returned as float64, not string (though they are posted as string),
	// defect #96322248...
	if floatVal, ok := fields["unix_uid"].(float64); ok {
		user.Uid = strconv.FormatInt(int64(floatVal), 10)
	}
	if floatVal, ok := fields["unix_guid"].(float64); ok {
		user.Gid = strconv.FormatInt(int64(floatVal), 10)
	}

	if _, exists := fields["enable_managed_uid"]; exists {
		user.EnableManagedUid = fields["enable_managed_uid"].(bool)
	}

	if _, exists := fields["password_expired"]; exists {
		user.PasswordExpired = fields["password_expired"].(bool)
	}

	if _, exists := fields["password_date"]; exists {
		user.PasswordDate = fields["password_date"].(string)
	}
}

func getJCUsersFromInterface(userInt interface{}) []JCUser {

	var returnVal []JCUser

	recMap := userInt.(map[string]interface{})

	results := recMap["results"].([]interface{})

	returnVal = make([]JCUser, len(results))

	for idx, result := range results {
		getJCUserFieldsFromInterface(result.(map[string]interface{}), &returnVal[idx])
	}

	return returnVal
}

// Executes a search by email via the JumpCloud API
func (jc JCAPI) GetSystemUserByEmail(email string, withTags bool) ([]JCUser, JCError) {
	var returnVal []JCUser

	jcUserRec, err := jc.Post("/search/systemusers", jc.emailFilter(email))
	if err != nil {
		return nil, fmt.Errorf("ERROR: Post to JumpCloud failed, err='%s'", err)
	}

	returnVal = getJCUsersFromInterface(jcUserRec)

	if withTags {
		tags, err := jc.GetAllTags()
		if err != nil {
			return nil, fmt.Errorf("ERROR: Could not get tags, err='%s'", err)
		}

		for idx, _ := range returnVal {
			returnVal[idx].AddJCTags(tags)
		}
	}

	return returnVal, nil
}

func (jc JCAPI) GetSystemUserById(userId string, withTags bool) (user JCUser, err JCError) {
	url := fmt.Sprintf("/systemusers/%s", userId)

	retVal, err := jc.Get(url)
	if err != nil {
		err = fmt.Errorf("ERROR: Could not get system user by ID '%s', err='%s'", userId, err)
	}

	if retVal != nil {
		getJCUserFieldsFromInterface(retVal.(map[string]interface{}), &user)

		if withTags {
			// I should be able to use err below as the err return value, but there's
			// a compiler bug here in that it thinks a := of err is shadowed here,
			// even though tags should be the only variable declared with the :=
			tags, err2 := jc.GetAllTags()
			if err != nil {
				err = fmt.Errorf("ERROR: Could not get tags, err='%s'", err2)
				return
			}

			user.AddJCTags(tags)
			setTagIds(&user)
		}
	}

	return
}

func (jc JCAPI) GetSystemUsers(withTags bool) (userList []JCUser, err JCError) {
	var returnVal []JCUser

	for skip := 0; skip == 0 || len(returnVal) == searchLimit; skip += searchSkipInterval {
		url := fmt.Sprintf("/systemusers?sort=username&skip=%d&limit=%d", skip, searchLimit)

		jcUserRec, err2 := jc.Get(url)
		if err != nil {
			return nil, fmt.Errorf("ERROR: Post to JumpCloud failed, err='%s'", err2)
		}

		if jcUserRec == nil {
			return nil, fmt.Errorf("ERROR: No users found")
		}

		// We really only care about the ID for the following call...
		returnVal = getJCUsersFromInterface(jcUserRec)

		for i, _ := range returnVal {
			if returnVal[i].Id != "" {

				//
				// Get the rest of the user record, which includes details like
				// the externalDN...
				//
				// We'll get all the tags one time later, so don't get the tags on this call...
				//
				// See above about the compiler error that requires me to use err2 instead of err below...
				//
				detailedUser, err2 := jc.GetSystemUserById(returnVal[i].Id, false)
				if err != nil {
					err = fmt.Errorf("ERROR: Could not get details for user ID '%s', err='%s'", returnVal[i].Id, err2)
					return
				}

				if detailedUser.Id != "" {
					userList = append(userList, detailedUser)
				}
			}
		}
	}

	if withTags {
		tags, err := jc.GetAllTags()
		if err != nil {
			return nil, fmt.Errorf("ERROR: Could not get tags, err='%s'", err)
		}

		for idx, _ := range userList {
			userList[idx].AddJCTags(tags)
			setTagIds(&userList[idx])
		}
	}

	return
}

//
// Resend user email
//
func (jc JCAPI) SendUserActivationEmail(userList []JCUser) (err JCError) {
	for _, user := range userList {
		if user.Id == "" {
			return fmt.Errorf("ERROR: Cannot resend user activation email without a systemuser Id on user %v", user)
		}
	}

	emailRequest := JCUserEmailRequest{
		IsSelectAll: false,
		Models:      userList,
	}

	data, err := json.Marshal(emailRequest)
	if err != nil {
		return fmt.Errorf("ERROR: Could not marshal JCUserEmailRequest object, err='%s'", err)
	}

	url := "/systemusers/reactivate"

	_, err = jc.Do(MapJCOpToHTTP(Insert), url, data)
	if err != nil {
		return fmt.Errorf("ERROR: Could not post resend email request object, err='%s'", err)
	}

	return
}

//
// Add or Update a new user to JumpCloud
//
func (jc JCAPI) AddUpdateUser(op JCOp, user JCUser) (userId string, err JCError) {
	if user.Password != "" {
		user.PasswordDate = getTimeString()
	}

	data, err := json.Marshal(user)
	if err != nil {
		return "", fmt.Errorf("ERROR: Could not marshal JCUser object, err='%s'", err)
	}

	url := "/systemusers"
	if op == Update {
		url += "/" + user.Id
	}

	jcUserRec, err := jc.Do(MapJCOpToHTTP(op), url, data)
	if err != nil {
		return "", fmt.Errorf("ERROR: Could not post new JCUser object, err='%s'", err)
	}

	var returnUser JCUser
	getJCUserFieldsFromInterface(jcUserRec.(map[string]interface{}), &returnUser)

	if returnUser.Email != user.Email {
		return "", fmt.Errorf("ERROR: JumpCloud did not return the same email - this should never happen!")
	}

	userId = returnUser.Id

	return
}

func (jc JCAPI) DeleteUser(user JCUser) JCError {
	_, err := jc.Delete(fmt.Sprintf("/systemusers/%s", user.Id))
	if err != nil {
		return fmt.Errorf("ERROR: Could not delete user '%s': err='%s'", user.Email, err)
	}

	return nil
}
<|endoftext|>


<commit_before>package model

import (
	"strconv"

	"github.com/google/go-github/github"
	"github.com/jinzhu/gorm"
)

// Star represents a starred repository
type Star struct {
	gorm.Model
	RemoteID    string
	Name        *string
	FullName    *string
	Description *string
	Homepage    *string
	URL         *string
	Language    *string
	Stargazers  int
	ServiceID   uint
	Tags        []Tag `gorm:"many2many:star_tags;"`
}

// StarResult wraps a star and an error
type StarResult struct {
	Star  *Star
	Error error
}

// NewStarFromGithub creates a Star from a Github star
func NewStarFromGithub(star github.Repository) *Star {
	return &Star{
		RemoteID:    strconv.Itoa(*star.ID),
		Name:        star.Name,
		FullName:    star.FullName,
		Description: star.Description,
		Homepage:    star.Homepage,
		URL:         star.CloneURL,
		Language:    star.Language,
		Stargazers:  *star.StargazersCount,
	}
}

// StarCopy copies values from src to dest
func StarCopy(src *Star, dest *Star) {
	dest.Name = src.Name
	dest.FullName = src.FullName
	dest.Description = src.Description
	dest.Homepage = src.Homepage
	dest.URL = src.URL
	dest.Language = src.Language
	dest.Stargazers = src.Stargazers
}

// CreateOrUpdateStar creates or updates a star and returns true if the star was created (vs updated)
func CreateOrUpdateStar(db *gorm.DB, star *Star, service *Service) (bool, error) {
	// Get existing by remote ID and service ID
	var existing Star
	if db.Where("remote_id = ? AND service_id = ?", star.RemoteID, service.ID).First(&existing).RecordNotFound() {
		star.ServiceID = service.ID
		err := db.Create(star).Error
		return err == nil, err
	}
	StarCopy(star, &existing)
	return false, db.Save(&existing).Error
}
<commit_msg>Add FindStarsWithLanguageAndTag<commit_after>package model

import (
	"strconv"

	"github.com/google/go-github/github"
	"github.com/jinzhu/gorm"
)

// Star represents a starred repository
type Star struct {
	gorm.Model
	RemoteID    string
	Name        *string
	FullName    *string
	Description *string
	Homepage    *string
	URL         *string
	Language    *string
	Stargazers  int
	ServiceID   uint
	Tags        []Tag `gorm:"many2many:star_tags;"`
}

// StarResult wraps a star and an error
type StarResult struct {
	Star  *Star
	Error error
}

// NewStarFromGithub creates a Star from a Github star
func NewStarFromGithub(star github.Repository) *Star {
	return &Star{
		RemoteID:    strconv.Itoa(*star.ID),
		Name:        star.Name,
		FullName:    star.FullName,
		Description: star.Description,
		Homepage:    star.Homepage,
		URL:         star.CloneURL,
		Language:    star.Language,
		Stargazers:  *star.StargazersCount,
	}
}

// StarCopy copies values from src to dest
func StarCopy(src *Star, dest *Star) {
	dest.Name = src.Name
	dest.FullName = src.FullName
	dest.Description = src.Description
	dest.Homepage = src.Homepage
	dest.URL = src.URL
	dest.Language = src.Language
	dest.Stargazers = src.Stargazers
}

// CreateOrUpdateStar creates or updates a star and returns true if the star was created (vs updated)
func CreateOrUpdateStar(db *gorm.DB, star *Star, service *Service) (bool, error) {
	// Get existing by remote ID and service ID
	var existing Star
	if db.Where("remote_id = ? AND service_id = ?", star.RemoteID, service.ID).First(&existing).RecordNotFound() {
		star.ServiceID = service.ID
		err := db.Create(star).Error
		return err == nil, err
	}
	StarCopy(star, &existing)
	return false, db.Save(&existing).Error
}

// FindStarsWithLanguageAndTag finds stars with the specified language and tag
func FindStarsWithLanguageAndTag(db *gorm.DB, language string, tag string) ([]Star, error) {
	var stars []Star

	if language != "" && tag != "" {
		db.Where("language = ? AND tag = ?", language, tag).Order("full_name").Find(&stars)
	} else if language != "" {
		db.Where("language = ?", language).Order("full_name").Find(&stars)
	} else if tag != "" {
		db.Where("tag = ?", tag).Order("full_name").Find(&stars)
	} else {
		db.Order("full_name").Find(&stars)
	}

	return stars, db.Error
}
<|endoftext|>


<commit_before>package titan

import (
	"github.com/neptulon/neptulon"
	"github.com/neptulon/neptulon/middleware"
	"github.com/titan-x/titan/data"
)

func initPubRoutes(r *middleware.Router, db *data.DB, pass string) {
	r.Request("auth.google", initGoogleAuthHandler(db, pass))
}

func initGoogleAuthHandler(db *data.DB, pass string) func(ctx *neptulon.ReqCtx) error {
	return func(ctx *neptulon.ReqCtx) error {
		if err := googleAuth(ctx, *db, pass); err != nil {
			return err
		}
		return nil
	}
}
<commit_msg>pub-routes: add explanation for *data.DB usage<commit_after>package titan

import (
	"github.com/neptulon/neptulon"
	"github.com/neptulon/neptulon/middleware"
	"github.com/titan-x/titan/data"
)

// we need *data.DB (pointer to interface) so that the closure below won't capture the actual value that pointer points to
// so we can swap databases whenever we want using Server.SetDB(...)
func initPubRoutes(r *middleware.Router, db *data.DB, pass string) {
	r.Request("auth.google", initGoogleAuthHandler(db, pass))
}

func initGoogleAuthHandler(db *data.DB, pass string) func(ctx *neptulon.ReqCtx) error {
	return func(ctx *neptulon.ReqCtx) error {
		if err := googleAuth(ctx, *db, pass); err != nil {
			return err
		}
		return nil
	}
}
<|endoftext|>


<commit_before>package colorable

import (
	"bytes"
	"os"
	"runtime"
	"testing"
)

// checkEncoding checks that colorable is output encoding agnostic as long as
// the encoding is a superset of ASCII. This implies that one byte not part of
// an ANSI sequence must give exactly one byte in output
func checkEncoding(t *testing.T, data []byte) {
	// Send non-UTF8 data to colorable
	b := bytes.NewBuffer(make([]byte, 0, 10))
	if b.Len() != 0 {
		t.FailNow()
	}
	// TODO move colorable wrapping outside the test
	c := NewNonColorable(b)
	c.Write(data)
	if b.Len() != len(data) {
		t.Fatalf("%d bytes expected, got %d", len(data), b.Len())
	}
}

func TestEncoding(t *testing.T) {
	checkEncoding(t, []byte{})      // Empty
	checkEncoding(t, []byte(`abc`)) // "abc"
	checkEncoding(t, []byte(`é`))   // "é" in UTF-8
	checkEncoding(t, []byte{233})   // 'é' in Latin-1
}

func TestNonColorable(t *testing.T) {
	var buf bytes.Buffer
	want := "hello"
	NewNonColorable(&buf).Write([]byte("\x1b[0m" + want + "\x1b[2J"))
	got := buf.String()
	if got != "hello" {
		t.Fatalf("want %q but %q", want, got)
	}

	buf.Reset()
	NewNonColorable(&buf).Write([]byte("\x1b["))
	got = buf.String()
	if got != "" {
		t.Fatalf("want %q but %q", "", got)
	}
}

func TestColorable(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skipf("skip this test on windows")
	}
	_, ok := NewColorableStdout().(*os.File)
	if !ok {
		t.Fatalf("should os.Stdout on UNIX")
	}
	_, ok = NewColorableStderr().(*os.File)
	if !ok {
		t.Fatalf("should os.Stdout on UNIX")
	}
	_, ok = NewColorable(os.Stdout).(*os.File)
	if !ok {
		t.Fatalf("should os.Stdout on UNIX")
	}
}
<commit_msg>add test<commit_after>package colorable

import (
	"bytes"
	"os"
	"runtime"
	"testing"
)

// checkEncoding checks that colorable is output encoding agnostic as long as
// the encoding is a superset of ASCII. This implies that one byte not part of
// an ANSI sequence must give exactly one byte in output
func checkEncoding(t *testing.T, data []byte) {
	// Send non-UTF8 data to colorable
	b := bytes.NewBuffer(make([]byte, 0, 10))
	if b.Len() != 0 {
		t.FailNow()
	}
	// TODO move colorable wrapping outside the test
	c := NewNonColorable(b)
	c.Write(data)
	if b.Len() != len(data) {
		t.Fatalf("%d bytes expected, got %d", len(data), b.Len())
	}
}

func TestEncoding(t *testing.T) {
	checkEncoding(t, []byte{})      // Empty
	checkEncoding(t, []byte(`abc`)) // "abc"
	checkEncoding(t, []byte(`é`))   // "é" in UTF-8
	checkEncoding(t, []byte{233})   // 'é' in Latin-1
}

func TestNonColorable(t *testing.T) {
	var buf bytes.Buffer
	want := "hello"
	NewNonColorable(&buf).Write([]byte("\x1b[0m" + want + "\x1b[2J"))
	got := buf.String()
	if got != "hello" {
		t.Fatalf("want %q but %q", want, got)
	}

	buf.Reset()
	NewNonColorable(&buf).Write([]byte("\x1b["))
	got = buf.String()
	if got != "" {
		t.Fatalf("want %q but %q", "", got)
	}
}

func TestNonColorableNil(t *testing.T) {
	paniced := false
	func() {
		defer func() {
			recover()
			paniced = true
		}()
		NewNonColorable(nil)
	}()

	if !paniced {
		t.Fatalf("should panic")
	}
}

func TestColorable(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skipf("skip this test on windows")
	}
	_, ok := NewColorableStdout().(*os.File)
	if !ok {
		t.Fatalf("should os.Stdout on UNIX")
	}
	_, ok = NewColorableStderr().(*os.File)
	if !ok {
		t.Fatalf("should os.Stdout on UNIX")
	}
	_, ok = NewColorable(os.Stdout).(*os.File)
	if !ok {
		t.Fatalf("should os.Stdout on UNIX")
	}
}
<|endoftext|>


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

package processing

import (
	"archive/zip"
	"io"
	"math"

	"go.chromium.org/luci/common/errors"
)

// TODO(vadimsh): Share code with the client.

// PackageReader knows how to extract files from CIPD packages.
//
// CIPD packages are actually zip archives, but we don't want to expose it
// everywhere.
type PackageReader struct {
	zr *zip.Reader
}

// NewPackageReader opens the package by reading its directory.
func NewPackageReader(r io.ReaderAt, size int64) (*PackageReader, error) {
	zr, err := zip.NewReader(r, size)
	if err != nil {
		// Note: we rely here (and in other places where we return errors) on
		// zip.Reader NOT wrapping errors from 'r', so they inherit transient tags
		// in case of transient Google Storage errors.
		return nil, err
	}
	return &PackageReader{zr}, nil
}

// Open opens some file inside the package for reading.
//
// Returns the ReadCloser and the uncompressed file size.
func (p *PackageReader) Open(path string) (io.ReadCloser, int64, error) {
	for _, f := range p.zr.File {
		if f.Name == path {
			if f.UncompressedSize64 > math.MaxInt64 {
				return nil, 0, errors.Reason("the file %q is unbelievably huge (%d bytes)", path, f.UncompressedSize64).Err()
			}
			rc, err := f.Open()
			if err != nil {
				return nil, 0, err
			}
			return rc, int64(f.UncompressedSize64), nil
		}
	}
	return nil, 0, errors.Reason("no file %q inside the package", path).Err()
}
<commit_msg>[cipd] Switch to klauspost/compress on the backend.<commit_after>// Copyright 2018 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package processing

import (
	"io"
	"math"

	"github.com/klauspost/compress/zip"

	"go.chromium.org/luci/common/errors"
)

// TODO(vadimsh): Share code with the client.

// PackageReader knows how to extract files from CIPD packages.
//
// CIPD packages are actually zip archives, but we don't want to expose it
// everywhere.
type PackageReader struct {
	zr *zip.Reader
}

// NewPackageReader opens the package by reading its directory.
func NewPackageReader(r io.ReaderAt, size int64) (*PackageReader, error) {
	zr, err := zip.NewReader(r, size)
	if err != nil {
		// Note: we rely here (and in other places where we return errors) on
		// zip.Reader NOT wrapping errors from 'r', so they inherit transient tags
		// in case of transient Google Storage errors.
		return nil, err
	}
	return &PackageReader{zr}, nil
}

// Open opens some file inside the package for reading.
//
// Returns the ReadCloser and the uncompressed file size.
func (p *PackageReader) Open(path string) (io.ReadCloser, int64, error) {
	for _, f := range p.zr.File {
		if f.Name == path {
			if f.UncompressedSize64 > math.MaxInt64 {
				return nil, 0, errors.Reason("the file %q is unbelievably huge (%d bytes)", path, f.UncompressedSize64).Err()
			}
			rc, err := f.Open()
			if err != nil {
				return nil, 0, err
			}
			return rc, int64(f.UncompressedSize64), nil
		}
	}
	return nil, 0, errors.Reason("no file %q inside the package", path).Err()
}
<|endoftext|>