<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/gdamore/tcell"
	"github.com/gdamore/tcell/encoding"
	runewidth "github.com/mattn/go-runewidth"
)

type keyStructType struct {
	r    rune
	name string
}

var row = 0
var style = tcell.StyleDefault

func putln(scrn tcell.Screen, str string) {
	puts(scrn, style, 1, row, str)
	row++
}

func putfln(scrn tcell.Screen, format string, args ...interface{}) {
	s := fmt.Sprintf(format, args...)
	puts(scrn, style, 1, row, s)
	row++
}

func putf(scrn tcell.Screen, style tcell.Style, x, y int, format string, args ...interface{}) {
	s := fmt.Sprintf(format, args...)
	puts(scrn, style, x, y, s)
}

func deleol(scrn tcell.Screen, style tcell.Style, x, y int)  {
	width, _ := scrn.Size()  // don't need height for this calculation.
	empty := width - x       // don't care if this is off by 1.
	blanks := make([]byte,empty)
	for i := range blanks {
		blanks[i] = ' '
	}
    blankstring := string(blanks)
    puts(scrn, style, x, y, blankstring)
}

func puts(scrn tcell.Screen, style tcell.Style, x, y int, str string) {
	i := 0
	var deferred []rune
	dwidth := 0
	zwj := false
	for _, r := range str {
		if r == '\u200d' {
			if len(deferred) == 0 {
				deferred = append(deferred, ' ')
				dwidth = 1
			}
			deferred = append(deferred, r)
			zwj = true
			continue
		}
		if zwj {
			deferred = append(deferred, r)
			zwj = false
			continue
		}
		switch runewidth.RuneWidth(r) {
		case 0:
			if len(deferred) == 0 {
				deferred = append(deferred, ' ')
				dwidth = 1
			}
		case 1:
			if len(deferred) != 0 {
				scrn.SetContent(x+i, y, deferred[0], deferred[1:], style)
				i += dwidth
			}
			deferred = nil
			dwidth = 1
		case 2:
			if len(deferred) != 0 {
				scrn.SetContent(x+i, y, deferred[0], deferred[1:], style)
				i += dwidth
			}
			deferred = nil
			dwidth = 2
		}
		deferred = append(deferred, r)
	}
	if len(deferred) != 0 {
		scrn.SetContent(x+i, y, deferred[0], deferred[1:], style)
		i += dwidth
	}
}

func main() {

	scrn, e := tcell.NewScreen()
	if e != nil {
		fmt.Fprintf(os.Stderr, "%v\n", e)
		os.Exit(1)
	}

	encoding.Register()

	if e = scrn.Init(); e != nil {
		fmt.Fprintf(os.Stderr, "%v\n", e)
		os.Exit(1)
	}

	defer scrn.Fini()

	plain := tcell.StyleDefault
	bold := style.Bold(true)

//	scrn.SetStyle(tcell.StyleDefault.
//		Foreground(tcell.ColorBlack).
//		Background(tcell.ColorWhite))
	scrn.SetStyle(tcell.StyleDefault.            // reversing the colors
		Foreground(tcell.ColorWhite).
		Background(tcell.ColorBlack))
	scrn.Clear()

	style = bold
	putln(scrn, "Press ESC to Exit")
	putln(scrn, "Character set: "+scrn.CharacterSet())
	style = plain

	putln(scrn, "English:   October")
	putln(scrn, "Icelandic: október")
	putln(scrn, "Arabic:    أكتوبر")
	putln(scrn, "Russian:   октября")
	putln(scrn, "Greek:     Οκτωβρίου")
	putln(scrn, "Chinese:   十月 (note, two double wide characters)")
	putln(scrn, "Combining: A\u030a (should look like Angstrom)")
	putln(scrn, "Emoticon:  \U0001f618 (blowing a kiss)")
	putln(scrn, "Airplane:  \u2708 (fly away)")
	putln(scrn, "Command:   \u2318 (mac clover key)")
	putln(scrn, "Enclose:   !\u20e3 (should be enclosed exclamation)")
	putln(scrn, "ZWJ:       \U0001f9db\u200d\u2640 (female vampire)")
	putln(scrn, "ZWJ:       \U0001f9db\u200d\u2642 (male vampire)")
	putln(scrn, "Family:    \U0001f469\u200d\U0001f467\u200d\U0001f467 (woman girl girl)\n")
	putln(scrn, "Region:    \U0001f1fa\U0001f1f8 (USA! USA!)\n")
	putln(scrn, "")
	putln(scrn, "Box:")
	putln(scrn, string([]rune{
		tcell.RuneULCorner,
		tcell.RuneHLine,
		tcell.RuneTTee,
		tcell.RuneHLine,
		tcell.RuneURCorner,
	}))
	putln(scrn, string([]rune{
		tcell.RuneVLine,
		tcell.RuneBullet,
		tcell.RuneVLine,
		tcell.RuneLantern,
		tcell.RuneVLine,
	})+"  (bullet, lantern/section)")
	putln(scrn, string([]rune{
		tcell.RuneLTee,
		tcell.RuneHLine,
		tcell.RunePlus,
		tcell.RuneHLine,
		tcell.RuneRTee,
	}))
	putln(scrn, string([]rune{
		tcell.RuneVLine,
		tcell.RuneDiamond,
		tcell.RuneVLine,
		tcell.RuneUArrow,
		tcell.RuneVLine,
	})+"  (diamond, up arrow)")
	putln(scrn, string([]rune{
		tcell.RuneLLCorner,
		tcell.RuneHLine,
		tcell.RuneBTee,
		tcell.RuneHLine,
		tcell.RuneLRCorner,
	}))

	width, height := scrn.Size()
	putfln(scrn, "from putfln.  Screen width: %d, height: %d", width, height)
	putf(scrn, style, 1, 17, " testing putf with a %s", "string I just typed.")

	scrn.Show()

	prompt := "enter a word:"

	for i := 0; i < 20; i++ {
		puts(scrn, style, 1, height-1, prompt)
		str := GetInputString(scrn, len(prompt)+4, height-1)
		if len(str) == 0 {
			break // return from main is same as os.Exit(0)
		}
		putln(scrn, str)
		putfln(scrn, "from putfln: %s", str)
		scrn.Show()
		if row >= height {
			break
		}
	}

//	scrn.Fini()  I don't need this because I already deferred a scrn.Fini() right after a successful init.
}

// --------------------------------------------------- GetInputString --------------------------------------

func GetInputString(scrn tcell.Screen, x, y int) string {

	deleol(scrn, style, x, y)
	scrn.ShowCursor(x, y)
	scrn.Show()
	donechan := make(chan bool)
	keychannl := make(chan rune)
	helpchan := make(chan bool)
	delchan := make(chan bool)
	upchan := make(chan bool)
	downchan := make(chan bool)
	homechan := make(chan bool)
	endchan := make(chan bool)
	leftchan := make(chan bool)
	rightchan := make(chan bool)

	pollevent := func() {
		for {
			event := scrn.PollEvent()
			switch event := event.(type) {
			case *tcell.EventKey:
				switch event.Key() {
				case tcell.KeyEscape, tcell.KeyEnter:
					donechan <- true // I don't have to send true to quit.
					return
				case tcell.KeyCtrlL:
					scrn.Sync()
				case tcell.KeyF1, tcell.KeyF2:
					// help
					helpchan <- true
					return

				case tcell.KeyBackspace, tcell.KeyDEL, tcell.KeyDelete:
					delchan <- true
					// do not return after any of these keys are hit, as an entry is being edited.

				case tcell.KeyPgUp, tcell.KeyUp:
					upchan <- true
					return

				case tcell.KeyPgDn, tcell.KeyDown:
					downchan <- true
					return

				case tcell.KeyRight, tcell.KeyUpRight, tcell.KeyDownRight:
					rightchan <- true
					return

				case tcell.KeyLeft, tcell.KeyUpLeft, tcell.KeyDownLeft:
					leftchan <- true
					return

				case tcell.KeyHome:
					homechan <- true
					return

				case tcell.KeyEnd:
					endchan <- true
					return

				case tcell.KeyRune:
					r := event.Rune()
					keychannl <- r
					if r == ' ' {
						return
					}
				}
			case *tcell.EventResize:
				scrn.Sync()
			}
		}
	}

	go pollevent()

	bs := make([]byte, 0, 100) // byteslice to build up the string to be returned.
	for {
		select {
		case <-donechan: // reading from quitchan will block until its closed.
			return string(bs)

		case <-helpchan:
			putfln(scrn, "help message received.  %s", "enter key is delimiter")
			return "help"

		case <-delchan:
			if len(bs) > 0 {
				bs = bs[:len(bs)-1]
			}
			puts(scrn,style,x+len(bs),y," ")
			scrn.ShowCursor(x+len(bs),y)
			scrn.Show()

		case <-upchan:
			return "up key, pgup, upleft, upright"

		case <-downchan:
			return "down key, pgdn, downleft, downright"

		case <-homechan:
			return "home key"

		case <-endchan:
			return "end key"

		case <-rightchan:
			return "right arrow"

		case <-leftchan:
			return "left arrow"

		case key := <-keychannl:
			if key == ' ' {
				if len(bs) > 0 {
					return string(bs)
				} else {
					go pollevent() // need to restart the go routine to fetch more keys.
					continue       // discard this extaneous space
				}
			}
			bs = append(bs, byte(key))
			puts(scrn, style, x, y, string(bs))

			scrn.ShowCursor(x+len(bs), y)
			scrn.Show()
		}
	}
} // GetInputString
<commit_msg>12/29/2019 09:46:29 AM	modified:   tcellwords/tcellwords.go -- colors<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/gdamore/tcell"
	"github.com/gdamore/tcell/encoding"
	runewidth "github.com/mattn/go-runewidth"
)

type keyStructType struct {
	r    rune
	name string
}

var row = 0
var style = tcell.StyleDefault

func putln(scrn tcell.Screen, str string) {
	puts(scrn, style, 1, row, str)
	row++
}

func putfln(scrn tcell.Screen, format string, args ...interface{}) {
	s := fmt.Sprintf(format, args...)
	puts(scrn, style, 1, row, s)
	row++
}

func putf(scrn tcell.Screen, style tcell.Style, x, y int, format string, args ...interface{}) {
	s := fmt.Sprintf(format, args...)
	puts(scrn, style, x, y, s)
}

func deleol(scrn tcell.Screen, style tcell.Style, x, y int)  {
	width, _ := scrn.Size()  // don't need height for this calculation.
	empty := width - x       // don't care if this is off by 1.
	blanks := make([]byte,empty)
	for i := range blanks {
		blanks[i] = ' '
	}
    blankstring := string(blanks)
    puts(scrn, style, x, y, blankstring)
}

func puts(scrn tcell.Screen, style tcell.Style, x, y int, str string) {
	i := 0
	var deferred []rune
	dwidth := 0
	zwj := false
	for _, r := range str {
		if r == '\u200d' {
			if len(deferred) == 0 {
				deferred = append(deferred, ' ')
				dwidth = 1
			}
			deferred = append(deferred, r)
			zwj = true
			continue
		}
		if zwj {
			deferred = append(deferred, r)
			zwj = false
			continue
		}
		switch runewidth.RuneWidth(r) {
		case 0:
			if len(deferred) == 0 {
				deferred = append(deferred, ' ')
				dwidth = 1
			}
		case 1:
			if len(deferred) != 0 {
				scrn.SetContent(x+i, y, deferred[0], deferred[1:], style)
				i += dwidth
			}
			deferred = nil
			dwidth = 1
		case 2:
			if len(deferred) != 0 {
				scrn.SetContent(x+i, y, deferred[0], deferred[1:], style)
				i += dwidth
			}
			deferred = nil
			dwidth = 2
		}
		deferred = append(deferred, r)
	}
	if len(deferred) != 0 {
		scrn.SetContent(x+i, y, deferred[0], deferred[1:], style)
		i += dwidth
	}
}

func main() {

	scrn, e := tcell.NewScreen()
	if e != nil {
		fmt.Fprintf(os.Stderr, "%v\n", e)
		os.Exit(1)
	}

	encoding.Register()

	if e = scrn.Init(); e != nil {
		fmt.Fprintf(os.Stderr, "%v\n", e)
		os.Exit(1)
	}

	defer scrn.Fini()

	plain := tcell.StyleDefault
	bold := style.Bold(true)
	reverse := style.Reverse(true)
	reversedBlue := style.Background(tcell.ColorWhite).Foreground(tcell.ColorBlue)

//	scrn.SetStyle(tcell.StyleDefault.
//		Foreground(tcell.ColorBlack).
//		Background(tcell.ColorWhite))
	scrn.SetStyle(tcell.StyleDefault.            // reversing the colors
		Foreground(tcell.ColorWhite).
		Background(tcell.ColorBlack))
	scrn.Clear()

	style = bold
	putln(scrn, "Press ESC to Exit")
	putln(scrn, "Character set: "+scrn.CharacterSet())
	style = plain

	putln(scrn, "English:   October")
	putln(scrn, "Icelandic: október")
	putln(scrn, "Arabic:    أكتوبر")
	putln(scrn, "Russian:   октября")
	putln(scrn, "Greek:     Οκτωβρίου")
	putln(scrn, "Chinese:   十月 (note, two double wide characters)")
	putln(scrn, "Combining: A\u030a (should look like Angstrom)")
	putln(scrn, "Emoticon:  \U0001f618 (blowing a kiss)")
	putln(scrn, "Airplane:  \u2708 (fly away)")
	putln(scrn, "Command:   \u2318 (mac clover key)")
	putln(scrn, "Enclose:   !\u20e3 (should be enclosed exclamation)")
	putln(scrn, "ZWJ:       \U0001f9db\u200d\u2640 (female vampire)")
	putln(scrn, "ZWJ:       \U0001f9db\u200d\u2642 (male vampire)")
	putln(scrn, "Family:    \U0001f469\u200d\U0001f467\u200d\U0001f467 (woman girl girl)\n")
	putln(scrn, "Region:    \U0001f1fa\U0001f1f8 (USA! USA!)\n")
	putln(scrn, "")
	putln(scrn, "Box:")
	putln(scrn, string([]rune{
		tcell.RuneULCorner,
		tcell.RuneHLine,
		tcell.RuneTTee,
		tcell.RuneHLine,
		tcell.RuneURCorner,
	}))
	putln(scrn, string([]rune{
		tcell.RuneVLine,
		tcell.RuneBullet,
		tcell.RuneVLine,
		tcell.RuneLantern,
		tcell.RuneVLine,
	})+"  (bullet, lantern/section)")
	putln(scrn, string([]rune{
		tcell.RuneLTee,
		tcell.RuneHLine,
		tcell.RunePlus,
		tcell.RuneHLine,
		tcell.RuneRTee,
	}))
	putln(scrn, string([]rune{
		tcell.RuneVLine,
		tcell.RuneDiamond,
		tcell.RuneVLine,
		tcell.RuneUArrow,
		tcell.RuneVLine,
	})+"  (diamond, up arrow)")
	putln(scrn, string([]rune{
		tcell.RuneLLCorner,
		tcell.RuneHLine,
		tcell.RuneBTee,
		tcell.RuneHLine,
		tcell.RuneLRCorner,
	}))

	width, height := scrn.Size()
	putf(scrn, reversedBlue,0,row,"from putfln.  Screen width: %d, height: %d", width, height)
	row++
	putf(scrn, reverse, 1, 17, " testing putf with a %s", "string I just typed.")

	scrn.Show()

	prompt := "enter a word:"

	for i := 0; i < 20; i++ {
		puts(scrn, style, 1, height-1, prompt)
		str := GetInputString(scrn, len(prompt)+4, height-1)
		if len(str) == 0 {
			break // return from main is same as os.Exit(0)
		}
//		putln(scrn, str)   don't need to duplicate lines anymore
		putfln(scrn, "from putfln: %s", str)
		scrn.Show()
		if row >= height {
			break
		}
	}

//	scrn.Fini()  I don't need this because I already deferred a scrn.Fini() right after a successful init.
}

// --------------------------------------------------- GetInputString --------------------------------------

func GetInputString(scrn tcell.Screen, x, y int) string {

	deleol(scrn, style, x, y)
	scrn.ShowCursor(x, y)
	scrn.Show()
	donechan := make(chan bool)
	keychannl := make(chan rune)
	helpchan := make(chan bool)
	delchan := make(chan bool)
	upchan := make(chan bool)
	downchan := make(chan bool)
	homechan := make(chan bool)
	endchan := make(chan bool)
	leftchan := make(chan bool)
	rightchan := make(chan bool)

	pollevent := func() {
		for {
			event := scrn.PollEvent()
			switch event := event.(type) {
			case *tcell.EventKey:
				switch event.Key() {
				case tcell.KeyEscape, tcell.KeyEnter:
					donechan <- true // I don't have to send true to quit.
					return
				case tcell.KeyCtrlL:
					scrn.Sync()
				case tcell.KeyF1, tcell.KeyF2:
					// help
					helpchan <- true
					return

				case tcell.KeyBackspace, tcell.KeyDEL, tcell.KeyDelete:
					delchan <- true
					// do not return after any of these keys are hit, as an entry is being edited.

				case tcell.KeyPgUp, tcell.KeyUp:
					upchan <- true
					return

				case tcell.KeyPgDn, tcell.KeyDown:
					downchan <- true
					return

				case tcell.KeyRight, tcell.KeyUpRight, tcell.KeyDownRight:
					rightchan <- true
					return

				case tcell.KeyLeft, tcell.KeyUpLeft, tcell.KeyDownLeft:
					leftchan <- true
					return

				case tcell.KeyHome:
					homechan <- true
					return

				case tcell.KeyEnd:
					endchan <- true
					return

				case tcell.KeyRune:
					r := event.Rune()
					keychannl <- r
					if r == ' ' {
						return
					}
				}
			case *tcell.EventResize:
				scrn.Sync()
			}
		}
	}

	go pollevent()

	bs := make([]byte, 0, 100) // byteslice to build up the string to be returned.
	for {
		select {
		case <-donechan: // reading from quitchan will block until its closed.
			return string(bs)

		case <-helpchan:
			putfln(scrn, "help message received.  %s", "enter key is delimiter")
			return "help"

		case <-delchan:
			if len(bs) > 0 {
				bs = bs[:len(bs)-1]
			}
			puts(scrn,style,x+len(bs),y," ")
			scrn.ShowCursor(x+len(bs),y)
			scrn.Show()

		case <-upchan:
			return "up key, pgup, upleft, upright"

		case <-downchan:
			return "down key, pgdn, downleft, downright"

		case <-homechan:
			return "home key"

		case <-endchan:
			return "end key"

		case <-rightchan:
			return "right arrow"

		case <-leftchan:
			return "left arrow"

		case key := <-keychannl:
			if key == ' ' {
				if len(bs) > 0 {
					return string(bs)
				} else {
					go pollevent() // need to restart the go routine to fetch more keys.
					continue       // discard this extaneous space
				}
			}
			bs = append(bs, byte(key))
			puts(scrn, style, x, y, string(bs))

			scrn.ShowCursor(x+len(bs), y)
			scrn.Show()
		}
	}
} // GetInputString
<|endoftext|>


<commit_before>package data

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

type Asset struct {
	Currency string `json:"currency"`
	Issuer   string `json:"issuer,omitempty"`
}

func NewAsset(s string) (*Asset, error) {
	if s == "XRP" {
		return &Asset{
			Currency: s,
		}, nil
	}
	parts := strings.Split(s, "/")
	if len(parts) != 2 {
		return nil, fmt.Errorf("bad asset: %s", s)
	}
	return &Asset{
		Currency: parts[0],
		Issuer:   parts[1],
	}, nil
}

func (a *Asset) IsNative() bool {
	return a.Currency == "XRP"
}

func (a *Asset) Matches(amount *Amount) bool {
	return (a.IsNative() && amount.IsNative()) ||
		(a.Currency == amount.Currency.String() && a.Issuer == amount.Issuer.String())
}

func (a Asset) String() string {
	if a.IsNative() {
		return a.Currency
	}
	return fmt.Sprintf("%s/%s", a.Currency, a.Issuer)
}

type OrderBookOffer struct {
	Offer
	OwnerFunds      Value          `json:"owner_funds"`
	Quality         NonNativeValue `json:"quality"`
	TakerGetsFunded *Amount        `json:"taker_gets_funded"`
	TakerPaysFunded *Amount        `json:"taker_pays_funded"`
}

type AccountOffer struct {
	Flags      LedgerEntryFlag `json:"flags"`
	Quality    NonNativeValue  `json:"quality"`
	Sequence   uint32          `json:"seq"`
	TakerGets  Amount          `json:"taker_gets"`
	TakerPays  Amount          `json:"taker_pays"`
	Expiration *uint32         `json:"expiration"`
}

type AccountOfferSlice []AccountOffer

func (s AccountOfferSlice) Len() int           { return len(s) }
func (s AccountOfferSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s AccountOfferSlice) Less(i, j int) bool { return s[i].Sequence > s[j].Sequence }

func (s AccountOfferSlice) GetSequences(pays, gets *Asset) []uint32 {
	// TODO: improve performance
	var sequences []uint32
	for i := range s {
		if pays.Matches(&s[i].TakerPays) && gets.Matches(&s[i].TakerGets) {
			sequences = append(sequences, s[i].Sequence)
		}
	}
	return sequences
}

func (s AccountOfferSlice) Find(sequence uint32) int {
	return sort.Search(len(s), func(i int) bool {
		return s[i].Sequence <= sequence
	})
}

func (s AccountOfferSlice) Get(sequence uint32) *AccountOffer {
	if i := s.Find(sequence); i < len(s) && s[i].Sequence == sequence {
		return &s[i]
	}
	return nil
}

func defaultUint32(v *uint32) uint32 {
	if v == nil {
		return 0
	}
	return *v
}

func (s *AccountOfferSlice) Add(offer *Offer) bool {
	quality, err := offer.TakerPays.Divide(offer.TakerGets)
	if err != nil {
		panic(fmt.Sprintf("impossible quality: %s %s", offer.TakerPays, offer.TakerGets))
	}
	o := AccountOffer{
		Flags:      LedgerEntryFlag(defaultUint32((*uint32)(offer.Flags))),
		Sequence:   *offer.Sequence,
		TakerGets:  *offer.TakerGets,
		TakerPays:  *offer.TakerPays,
		Quality:    NonNativeValue{*quality.Value},
		Expiration: offer.Expiration,
	}
	i := s.Find(*offer.Sequence)
	switch {
	case i == len(*s):
		*s = append(*s, o)
		return true
	case (*s)[i].Sequence != *offer.Sequence:
		*s = append(*s, AccountOffer{})
		copy((*s)[i+1:], (*s)[i:])
		(*s)[i] = o
		return true
	default:
		return false
	}
}

func (s AccountOfferSlice) Update(offer *Offer) bool {
	if existing := s.Get(*offer.Sequence); existing != nil {
		existing.TakerGets = *offer.TakerGets
		existing.TakerPays = *offer.TakerPays
		return true
	}
	return false
}

func (s *AccountOfferSlice) Delete(offer *Offer) bool {
	if i := s.Find(*offer.Sequence); i < len(*s) && (*s)[i].Sequence == *offer.Sequence {
		*s = append((*s)[:i], (*s)[i+1:]...)
		return true
	}
	return false
}

type AccountLine struct {
	Account        Account        `json:"account"`
	Balance        NonNativeValue `json:"balance"`
	Currency       Currency       `json:"currency"`
	Limit          NonNativeValue `json:"limit"`
	LimitPeer      NonNativeValue `json:"limit_peer"`
	NoRipple       bool           `json:"no_ripple"`
	NoRipplePeer   bool           `json:"no_ripple_peer"`
	Authorized     bool           `json:"authorized"`
	AuthorizedPeer bool           `json:"peer_authorized"`
	Freeze         bool           `json:"freeze"`
	FreezePeer     bool           `json:"freeze_peer"`
	QualityIn      uint32         `json:"quality_in"`
	QualityOut     uint32         `json:"quality_out"`
}

func (l *AccountLine) Asset() *Asset {
	return &Asset{
		Currency: l.Currency.String(),
		Issuer:   l.Account.String(),
	}
}

func (l *AccountLine) CompareByCurrencyAccount(other *AccountLine) int {
	if cmp := l.Currency.Compare(other.Currency); cmp != 0 {
		return cmp
	}
	return l.Account.Compare(other.Account)
}

func (l *AccountLine) CompareByCurrencyAmount(other *AccountLine) int {
	if cmp := l.Currency.Compare(other.Currency); cmp != 0 {
		return cmp
	}
	return l.Balance.Abs().Compare(*other.Balance.Abs())
}

type AccountLineSlice []AccountLine

type byCurrencyAccount struct {
	AccountLineSlice
}

func (by *byCurrencyAccount) Less(i, j int) bool {
	return by.AccountLineSlice[i].CompareByCurrencyAccount(&by.AccountLineSlice[j]) < 0
}

type byCurrencyAmount struct {
	AccountLineSlice
}

func (by *byCurrencyAmount) Less(i, j int) bool {
	return by.AccountLineSlice[i].CompareByCurrencyAmount(&by.AccountLineSlice[j]) < 0
}

func (s AccountLineSlice) Len() int               { return len(s) }
func (s AccountLineSlice) Swap(i, j int)          { s[i], s[j] = s[j], s[i] }
func (s AccountLineSlice) SortbyCurrencyAccount() { sort.Sort(&byCurrencyAccount{s}) }
func (s AccountLineSlice) SortByCurrencyAmount()  { sort.Sort(&byCurrencyAmount{s}) }

func (s AccountLineSlice) Find(account Account, currency Currency) int {
	return sort.Search(len(s), func(i int) bool {
		switch s[i].Currency.Compare(currency) {
		case 1:
			return true
		case -1:
			return false
		default:
			return s[i].Account.Compare(account) >= 0
		}
	})
}

func (s AccountLineSlice) Get(account Account, currency Currency) *AccountLine {
	if i := s.Find(account, currency); i < len(s) && s[i].Account.Equals(account) && s[i].Currency.Equals(currency) {
		return &s[i]
	}
	return nil
}

type highLowFunc func(balance, limit, limitPeer *Amount, noRipple, noRipplePeer bool, qualityIn, qualityOut uint32) bool

func highLow(account Account, rs *RippleState, f highLowFunc) bool {
	high, low := account.Equals(rs.HighLimit.Issuer), account.Equals(rs.LowLimit.Issuer)
	switch {
	case high == low:
		return false
	case high:
		noRipple, noRipplePeer := *rs.Flags&LsHighNoRipple > 0, *rs.Flags&LsLowNoRipple > 0
		return f(rs.Balance.Negate(), rs.HighLimit, rs.LowLimit, noRipple, noRipplePeer, defaultUint32(rs.HighQualityIn), defaultUint32(rs.HighQualityOut))
	default:
		noRipple, noRipplePeer := *rs.Flags&LsLowNoRipple > 0, *rs.Flags&LsHighNoRipple > 0
		return f(rs.Balance, rs.LowLimit, rs.HighLimit, noRipple, noRipplePeer, defaultUint32(rs.LowQualityIn), defaultUint32(rs.LowQualityOut))
	}
}

func (s *AccountLineSlice) Add(account Account, rs *RippleState) bool {
	var add = func(balance, limit, limitPeer *Amount, noRipple, noRipplePeer bool, qualityIn, qualityOut uint32) bool {
		line := AccountLine{
			Account:      limitPeer.Issuer,
			Balance:      NonNativeValue{*balance.Value},
			Currency:     limit.Currency,
			Limit:        NonNativeValue{*limit.Value},
			LimitPeer:    NonNativeValue{*limitPeer.Value},
			NoRipple:     noRipple,
			NoRipplePeer: noRipplePeer,
			QualityIn:    qualityIn,
			QualityOut:   qualityOut,
		}
		i := s.Find(limitPeer.Issuer, limitPeer.Currency)
		switch {
		case i == len(*s):
			*s = append(*s, line)
			return true
		case (*s)[i].Account.Equals(limitPeer.Issuer) && (*s)[i].Currency.Equals(limitPeer.Currency):
			return false
		default:
			*s = append((*s)[:i], append(AccountLineSlice{line}, (*s)[i:]...)...)
			return true
		}
	}
	return highLow(account, rs, add)
}

func (s AccountLineSlice) Update(account Account, rs *RippleState) bool {
	var update = func(balance, limit, limitPeer *Amount, noripple, noRipplePeer bool, qualityIn, qualityOut uint32) bool {
		i := s.Find(limitPeer.Issuer, limitPeer.Currency)
		if i == len(s) || !s[i].Account.Equals(limitPeer.Issuer) || !s[i].Currency.Equals(limitPeer.Currency) {
			return false
		}
		s[i].Balance = NonNativeValue{*balance.Value}
		s[i].Limit = NonNativeValue{*limit.Value}
		s[i].LimitPeer = NonNativeValue{*limitPeer.Value}
		s[i].NoRipple = noripple
		s[i].NoRipplePeer = noRipplePeer
		return true
	}
	return highLow(account, rs, update)
}

func (s *AccountLineSlice) Delete(account Account, rs *RippleState) bool {
	var del = func(balance, limit, limitPeer *Amount, noripple, noRipplePeer bool, qualityIn, qualityOut uint32) bool {
		i := s.Find(limitPeer.Issuer, limitPeer.Currency)
		if i < len(*s) && (*s)[i].Account.Equals(limitPeer.Issuer) && (*s)[i].Currency.Equals(limitPeer.Currency) {
			*s = append((*s)[:i], (*s)[i+1:]...)
			return true
		}
		return false
	}
	return highLow(account, rs, del)
}
<commit_msg>Add BalanceAmount() to AccountLine<commit_after>package data

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

type Asset struct {
	Currency string `json:"currency"`
	Issuer   string `json:"issuer,omitempty"`
}

func NewAsset(s string) (*Asset, error) {
	if s == "XRP" {
		return &Asset{
			Currency: s,
		}, nil
	}
	parts := strings.Split(s, "/")
	if len(parts) != 2 {
		return nil, fmt.Errorf("bad asset: %s", s)
	}
	return &Asset{
		Currency: parts[0],
		Issuer:   parts[1],
	}, nil
}

func (a *Asset) IsNative() bool {
	return a.Currency == "XRP"
}

func (a *Asset) Matches(amount *Amount) bool {
	return (a.IsNative() && amount.IsNative()) ||
		(a.Currency == amount.Currency.String() && a.Issuer == amount.Issuer.String())
}

func (a Asset) String() string {
	if a.IsNative() {
		return a.Currency
	}
	return fmt.Sprintf("%s/%s", a.Currency, a.Issuer)
}

type OrderBookOffer struct {
	Offer
	OwnerFunds      Value          `json:"owner_funds"`
	Quality         NonNativeValue `json:"quality"`
	TakerGetsFunded *Amount        `json:"taker_gets_funded"`
	TakerPaysFunded *Amount        `json:"taker_pays_funded"`
}

type AccountOffer struct {
	Flags      LedgerEntryFlag `json:"flags"`
	Quality    NonNativeValue  `json:"quality"`
	Sequence   uint32          `json:"seq"`
	TakerGets  Amount          `json:"taker_gets"`
	TakerPays  Amount          `json:"taker_pays"`
	Expiration *uint32         `json:"expiration"`
}

type AccountOfferSlice []AccountOffer

func (s AccountOfferSlice) Len() int           { return len(s) }
func (s AccountOfferSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s AccountOfferSlice) Less(i, j int) bool { return s[i].Sequence > s[j].Sequence }

func (s AccountOfferSlice) GetSequences(pays, gets *Asset) []uint32 {
	// TODO: improve performance
	var sequences []uint32
	for i := range s {
		if pays.Matches(&s[i].TakerPays) && gets.Matches(&s[i].TakerGets) {
			sequences = append(sequences, s[i].Sequence)
		}
	}
	return sequences
}

func (s AccountOfferSlice) Find(sequence uint32) int {
	return sort.Search(len(s), func(i int) bool {
		return s[i].Sequence <= sequence
	})
}

func (s AccountOfferSlice) Get(sequence uint32) *AccountOffer {
	if i := s.Find(sequence); i < len(s) && s[i].Sequence == sequence {
		return &s[i]
	}
	return nil
}

func defaultUint32(v *uint32) uint32 {
	if v == nil {
		return 0
	}
	return *v
}

func (s *AccountOfferSlice) Add(offer *Offer) bool {
	quality, err := offer.TakerPays.Divide(offer.TakerGets)
	if err != nil {
		panic(fmt.Sprintf("impossible quality: %s %s", offer.TakerPays, offer.TakerGets))
	}
	o := AccountOffer{
		Flags:      LedgerEntryFlag(defaultUint32((*uint32)(offer.Flags))),
		Sequence:   *offer.Sequence,
		TakerGets:  *offer.TakerGets,
		TakerPays:  *offer.TakerPays,
		Quality:    NonNativeValue{*quality.Value},
		Expiration: offer.Expiration,
	}
	i := s.Find(*offer.Sequence)
	switch {
	case i == len(*s):
		*s = append(*s, o)
		return true
	case (*s)[i].Sequence != *offer.Sequence:
		*s = append(*s, AccountOffer{})
		copy((*s)[i+1:], (*s)[i:])
		(*s)[i] = o
		return true
	default:
		return false
	}
}

func (s AccountOfferSlice) Update(offer *Offer) bool {
	if existing := s.Get(*offer.Sequence); existing != nil {
		existing.TakerGets = *offer.TakerGets
		existing.TakerPays = *offer.TakerPays
		return true
	}
	return false
}

func (s *AccountOfferSlice) Delete(offer *Offer) bool {
	if i := s.Find(*offer.Sequence); i < len(*s) && (*s)[i].Sequence == *offer.Sequence {
		*s = append((*s)[:i], (*s)[i+1:]...)
		return true
	}
	return false
}

type AccountLine struct {
	Account        Account        `json:"account"`
	Balance        NonNativeValue `json:"balance"`
	Currency       Currency       `json:"currency"`
	Limit          NonNativeValue `json:"limit"`
	LimitPeer      NonNativeValue `json:"limit_peer"`
	NoRipple       bool           `json:"no_ripple"`
	NoRipplePeer   bool           `json:"no_ripple_peer"`
	Authorized     bool           `json:"authorized"`
	AuthorizedPeer bool           `json:"peer_authorized"`
	Freeze         bool           `json:"freeze"`
	FreezePeer     bool           `json:"freeze_peer"`
	QualityIn      uint32         `json:"quality_in"`
	QualityOut     uint32         `json:"quality_out"`
}

func (l *AccountLine) Asset() *Asset {
	return &Asset{
		Currency: l.Currency.String(),
		Issuer:   l.Account.String(),
	}
}

func (l *AccountLine) BalanceAmount() *Amount {
	return &Amount{
		Value:    &l.Balance.Value,
		Currency: l.Currency,
		Issuer:   l.Account,
	}
}

func (l *AccountLine) CompareByCurrencyAccount(other *AccountLine) int {
	if cmp := l.Currency.Compare(other.Currency); cmp != 0 {
		return cmp
	}
	return l.Account.Compare(other.Account)
}

func (l *AccountLine) CompareByCurrencyAmount(other *AccountLine) int {
	if cmp := l.Currency.Compare(other.Currency); cmp != 0 {
		return cmp
	}
	return l.Balance.Abs().Compare(*other.Balance.Abs())
}

type AccountLineSlice []AccountLine

type byCurrencyAccount struct {
	AccountLineSlice
}

func (by *byCurrencyAccount) Less(i, j int) bool {
	return by.AccountLineSlice[i].CompareByCurrencyAccount(&by.AccountLineSlice[j]) < 0
}

type byCurrencyAmount struct {
	AccountLineSlice
}

func (by *byCurrencyAmount) Less(i, j int) bool {
	return by.AccountLineSlice[i].CompareByCurrencyAmount(&by.AccountLineSlice[j]) < 0
}

func (s AccountLineSlice) Len() int               { return len(s) }
func (s AccountLineSlice) Swap(i, j int)          { s[i], s[j] = s[j], s[i] }
func (s AccountLineSlice) SortbyCurrencyAccount() { sort.Sort(&byCurrencyAccount{s}) }
func (s AccountLineSlice) SortByCurrencyAmount()  { sort.Sort(&byCurrencyAmount{s}) }

func (s AccountLineSlice) Find(account Account, currency Currency) int {
	return sort.Search(len(s), func(i int) bool {
		switch s[i].Currency.Compare(currency) {
		case 1:
			return true
		case -1:
			return false
		default:
			return s[i].Account.Compare(account) >= 0
		}
	})
}

func (s AccountLineSlice) Get(account Account, currency Currency) *AccountLine {
	if i := s.Find(account, currency); i < len(s) && s[i].Account.Equals(account) && s[i].Currency.Equals(currency) {
		return &s[i]
	}
	return nil
}

type highLowFunc func(balance, limit, limitPeer *Amount, noRipple, noRipplePeer bool, qualityIn, qualityOut uint32) bool

func highLow(account Account, rs *RippleState, f highLowFunc) bool {
	high, low := account.Equals(rs.HighLimit.Issuer), account.Equals(rs.LowLimit.Issuer)
	switch {
	case high == low:
		return false
	case high:
		noRipple, noRipplePeer := *rs.Flags&LsHighNoRipple > 0, *rs.Flags&LsLowNoRipple > 0
		return f(rs.Balance.Negate(), rs.HighLimit, rs.LowLimit, noRipple, noRipplePeer, defaultUint32(rs.HighQualityIn), defaultUint32(rs.HighQualityOut))
	default:
		noRipple, noRipplePeer := *rs.Flags&LsLowNoRipple > 0, *rs.Flags&LsHighNoRipple > 0
		return f(rs.Balance, rs.LowLimit, rs.HighLimit, noRipple, noRipplePeer, defaultUint32(rs.LowQualityIn), defaultUint32(rs.LowQualityOut))
	}
}

func (s *AccountLineSlice) Add(account Account, rs *RippleState) bool {
	var add = func(balance, limit, limitPeer *Amount, noRipple, noRipplePeer bool, qualityIn, qualityOut uint32) bool {
		line := AccountLine{
			Account:      limitPeer.Issuer,
			Balance:      NonNativeValue{*balance.Value},
			Currency:     limit.Currency,
			Limit:        NonNativeValue{*limit.Value},
			LimitPeer:    NonNativeValue{*limitPeer.Value},
			NoRipple:     noRipple,
			NoRipplePeer: noRipplePeer,
			QualityIn:    qualityIn,
			QualityOut:   qualityOut,
		}
		i := s.Find(limitPeer.Issuer, limitPeer.Currency)
		switch {
		case i == len(*s):
			*s = append(*s, line)
			return true
		case (*s)[i].Account.Equals(limitPeer.Issuer) && (*s)[i].Currency.Equals(limitPeer.Currency):
			return false
		default:
			*s = append((*s)[:i], append(AccountLineSlice{line}, (*s)[i:]...)...)
			return true
		}
	}
	return highLow(account, rs, add)
}

func (s AccountLineSlice) Update(account Account, rs *RippleState) bool {
	var update = func(balance, limit, limitPeer *Amount, noripple, noRipplePeer bool, qualityIn, qualityOut uint32) bool {
		i := s.Find(limitPeer.Issuer, limitPeer.Currency)
		if i == len(s) || !s[i].Account.Equals(limitPeer.Issuer) || !s[i].Currency.Equals(limitPeer.Currency) {
			return false
		}
		s[i].Balance = NonNativeValue{*balance.Value}
		s[i].Limit = NonNativeValue{*limit.Value}
		s[i].LimitPeer = NonNativeValue{*limitPeer.Value}
		s[i].NoRipple = noripple
		s[i].NoRipplePeer = noRipplePeer
		return true
	}
	return highLow(account, rs, update)
}

func (s *AccountLineSlice) Delete(account Account, rs *RippleState) bool {
	var del = func(balance, limit, limitPeer *Amount, noripple, noRipplePeer bool, qualityIn, qualityOut uint32) bool {
		i := s.Find(limitPeer.Issuer, limitPeer.Currency)
		if i < len(*s) && (*s)[i].Account.Equals(limitPeer.Issuer) && (*s)[i].Currency.Equals(limitPeer.Currency) {
			*s = append((*s)[:i], (*s)[i+1:]...)
			return true
		}
		return false
	}
	return highLow(account, rs, del)
}
<|endoftext|>


<commit_before>// The following enables go generate to generate the doc.go file.
//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"regexp"

	"v.io/core/veyron2/uniqueid"
	"v.io/lib/cmdline"
)

func main() {
	os.Exit(cmdUniqueId.Main())
}

var cmdUniqueId = &cmdline.Command{
	Name:  "uniqueid",
	Short: "Generates UniqueIds.",
	Long: `
The uniqueid tool generates unique ids.
It also has an option of automatically substituting unique ids with placeholders in files.
`,
	Children: []*cmdline.Command{cmdGenerate, cmdInject},
	Topics:   []cmdline.Topic{},
}

var cmdGenerate = &cmdline.Command{
	Run:   runGenerate,
	Name:  "generate",
	Short: "Generates UniqueIds",
	Long: `
Generates unique ids and outputs them to standard out.
`,
	ArgsName: "",
	ArgsLong: "",
}

var cmdInject = &cmdline.Command{
	Run:   runInject,
	Name:  "inject",
	Short: "Injects UniqueIds into existing files",
	Long: `
Injects UniqueIds into existing files.
Strings of the form "$UNIQUEID$" will be replaced with generated ids.
`,
	ArgsName: "<filenames>",
	ArgsLong: "<filenames> List of files to inject unique ids into",
}

// runGenerate implements the generate command which outputs generated ids to stdout.
func runGenerate(command *cmdline.Command, args []string) error {
	if len(args) > 0 {
		return command.UsageErrorf("expected 0 args, got %d", len(args))
	}
	id, err := uniqueid.Random()
	if err != nil {
		return err
	}
	fmt.Printf("%#v", id)
	return nil
}

// runInject implements the inject command which replaces $UNIQUEID$ strings with generated ids.
func runInject(command *cmdline.Command, args []string) error {
	if len(args) == 0 {
		return command.UsageErrorf("expected at least one file arg, got 0")
	}
	for _, arg := range args {
		if err := injectIntoFile(arg); err != nil {
			return err
		}
	}
	return nil
}

// injectIntoFile replaces $UNIQUEID$ strings when they exist in the specified file.
func injectIntoFile(filename string) error {
	inbytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	// Replace $UNIQUEID$ with generated ids.
	re, err := regexp.Compile("[$]UNIQUEID")
	if err != nil {
		return err
	}
	replaced := re.ReplaceAllFunc(inbytes, func(match []byte) []byte {
		id, randErr := uniqueid.Random()
		if randErr != nil {
			err = randErr
		}
		return []byte(fmt.Sprintf("%#v", id))
	})
	if err != nil {
		return err
	}

	// If the file with injections is different, write it to disk.
	if !bytes.Equal(inbytes, replaced) {
		fmt.Printf("Updated: %s\n", filename)
		return ioutil.WriteFile(filename, replaced, 0)
	}
	return nil
}
<commit_msg>veyron/tools/uniqueid: Make generate print newline.<commit_after>// The following enables go generate to generate the doc.go file.
//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"regexp"

	"v.io/core/veyron2/uniqueid"
	"v.io/lib/cmdline"
)

func main() {
	os.Exit(cmdUniqueId.Main())
}

var cmdUniqueId = &cmdline.Command{
	Name:  "uniqueid",
	Short: "Generates UniqueIds.",
	Long: `
The uniqueid tool generates unique ids.
It also has an option of automatically substituting unique ids with placeholders in files.
`,
	Children: []*cmdline.Command{cmdGenerate, cmdInject},
	Topics:   []cmdline.Topic{},
}

var cmdGenerate = &cmdline.Command{
	Run:   runGenerate,
	Name:  "generate",
	Short: "Generates UniqueIds",
	Long: `
Generates unique ids and outputs them to standard out.
`,
	ArgsName: "",
	ArgsLong: "",
}

var cmdInject = &cmdline.Command{
	Run:   runInject,
	Name:  "inject",
	Short: "Injects UniqueIds into existing files",
	Long: `
Injects UniqueIds into existing files.
Strings of the form "$UNIQUEID$" will be replaced with generated ids.
`,
	ArgsName: "<filenames>",
	ArgsLong: "<filenames> List of files to inject unique ids into",
}

// runGenerate implements the generate command which outputs generated ids to stdout.
func runGenerate(command *cmdline.Command, args []string) error {
	if len(args) > 0 {
		return command.UsageErrorf("expected 0 args, got %d", len(args))
	}
	id, err := uniqueid.Random()
	if err != nil {
		return err
	}
	fmt.Printf("%#v\n", id)
	return nil
}

// runInject implements the inject command which replaces $UNIQUEID$ strings with generated ids.
func runInject(command *cmdline.Command, args []string) error {
	if len(args) == 0 {
		return command.UsageErrorf("expected at least one file arg, got 0")
	}
	for _, arg := range args {
		if err := injectIntoFile(arg); err != nil {
			return err
		}
	}
	return nil
}

// injectIntoFile replaces $UNIQUEID$ strings when they exist in the specified file.
func injectIntoFile(filename string) error {
	inbytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}

	// Replace $UNIQUEID$ with generated ids.
	re, err := regexp.Compile("[$]UNIQUEID")
	if err != nil {
		return err
	}
	replaced := re.ReplaceAllFunc(inbytes, func(match []byte) []byte {
		id, randErr := uniqueid.Random()
		if randErr != nil {
			err = randErr
		}
		return []byte(fmt.Sprintf("%#v", id))
	})
	if err != nil {
		return err
	}

	// If the file with injections is different, write it to disk.
	if !bytes.Equal(inbytes, replaced) {
		fmt.Printf("Updated: %s\n", filename)
		return ioutil.WriteFile(filename, replaced, 0)
	}
	return nil
}
<|endoftext|>


<commit_before>package dbshield

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"os"
	"os/signal"
	"strings"
	"time"

	"github.com/boltdb/bolt"
	"github.com/nim4/DBShield/dbshield/config"
	"github.com/nim4/DBShield/dbshield/dbms"
	"github.com/nim4/DBShield/dbshield/logger"
	"github.com/nim4/DBShield/dbshield/training"
	"github.com/nim4/DBShield/dbshield/utils"
)

const (
	mysql = iota
	postgres
	db2
	oracle
)

//initial boltdb database
func initModel(path string) {
	logger.Infof("Internal DB: %s", path)
	if training.DBCon == nil {
		training.DBCon, _ = bolt.Open(path, 0600, nil)
		training.DBCon.Update(func(tx *bolt.Tx) error {
			tx.CreateBucketIfNotExists([]byte("pattern"))
			tx.CreateBucketIfNotExists([]byte("abnormal"))
			b, _ := tx.CreateBucketIfNotExists([]byte("state"))
			v := b.Get([]byte("QueryCounter"))
			if v != nil {
				training.QueryCounter = binary.BigEndian.Uint64(v)
			}
			v = b.Get([]byte("AbnormalCounter"))
			if v != nil {
				training.AbnormalCounter = binary.BigEndian.Uint64(v)
			}
			return nil
		})
	}

	if config.Config.SyncInterval != 0 {
		training.DBCon.NoSync = true
		ticker := time.NewTicker(config.Config.SyncInterval)
		go func() {
			for range ticker.C {
				training.DBCon.Sync()
			}
		}()
	}
}

func closeHandlers() {
	if training.DBCon != nil {
		training.DBCon.Update(func(tx *bolt.Tx) error {
			//Supplied value must remain valid for the life of the transaction
			qCount := make([]byte, 8)
			abCount := make([]byte, 8)

			b := tx.Bucket([]byte("state"))
			binary.BigEndian.PutUint64(qCount, training.QueryCounter)
			b.Put([]byte("QueryCounter"), qCount)

			binary.BigEndian.PutUint64(abCount, training.AbnormalCounter)
			b.Put([]byte("AbnormalCounter"), abCount)

			return nil
		})
		training.DBCon.Sync()
		training.DBCon.Close()
	}
	if logger.Output != nil {
		logger.Output.Close()
	}
}

//catching Interrupts
func signalHandler() {
	term := make(chan os.Signal)
	signal.Notify(term, os.Interrupt)
	<-term
	logger.Info("Shutting down...")
	//Closing open handler politely
	closeHandlers()
}

//initLogging redirect log output to file/stdout/stderr
func initLogging() {
	err := logger.Init(config.Config.LogPath, config.Config.LogLevel)
	if err != nil {
		panic(err)
	}
}

//maps database name to corresponding struct
func dbNameToStruct(db string) (d uint, err error) {
	switch strings.ToLower(db) {
	case "db2":
		d = db2
	case "mssql":
		d = mssql
	case "mysql", "mariadb":
		d = mysql
	case "oracle":
		d = oracle
	case "postgres":
		d = postgres
	default:
		err = fmt.Errorf("Unknown DBMS: %s", db)
	}
	return
}

//generateDBMS instantiate a new instance of DBMS
func generateDBMS() (utils.DBMS, func(io.Reader) ([]byte, error)) {
	switch config.Config.DB {
	case mssql:
		return new(dbms.MSSQL), dbms.MSSQLReadPacket
	case mysql:
		return new(dbms.MySQL), dbms.MySQLReadPacket
	case postgres:
		return new(dbms.Postgres), dbms.ReadPacket //TODO: implement explicit reader
	case oracle:
		return new(dbms.Oracle), dbms.ReadPacket //TODO: implement explicit reader
	case db2:
		return new(dbms.DB2), dbms.ReadPacket //TODO: implement explicit reader
	default:
		return nil, nil
	}
}

func handleClient(listenConn net.Conn, serverAddr *net.TCPAddr) error {
	d, reader := generateDBMS()
	logger.Debugf("Connected from: %s", listenConn.RemoteAddr())
	serverConn, err := net.DialTCP("tcp", nil, serverAddr)
	if err != nil {
		logger.Warning(err)
		listenConn.Close()
		return err
	}
	if config.Config.Timeout > 0 {
		if err = listenConn.SetDeadline(time.Now().Add(config.Config.Timeout)); err != nil {
			return err
		}
		if err = serverConn.SetDeadline(time.Now().Add(config.Config.Timeout)); err != nil {
			return err
		}
	}
	logger.Debugf("Connected to: %s", serverConn.RemoteAddr())
	d.SetSockets(listenConn, serverConn)
	d.SetCertificate(config.Config.TLSCertificate, config.Config.TLSPrivateKey)
	d.SetReader(reader)
	err = d.Handler()
	if err != nil {
		logger.Warning(err)
	}
	return err
}
<commit_msg>Start working on MSSQL<commit_after>package dbshield

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"os"
	"os/signal"
	"strings"
	"time"

	"github.com/boltdb/bolt"
	"github.com/nim4/DBShield/dbshield/config"
	"github.com/nim4/DBShield/dbshield/dbms"
	"github.com/nim4/DBShield/dbshield/logger"
	"github.com/nim4/DBShield/dbshield/training"
	"github.com/nim4/DBShield/dbshield/utils"
)

const (
	mysql = iota
	mssql
	postgres
	db2
	oracle
)

//initial boltdb database
func initModel(path string) {
	logger.Infof("Internal DB: %s", path)
	if training.DBCon == nil {
		training.DBCon, _ = bolt.Open(path, 0600, nil)
		training.DBCon.Update(func(tx *bolt.Tx) error {
			tx.CreateBucketIfNotExists([]byte("pattern"))
			tx.CreateBucketIfNotExists([]byte("abnormal"))
			b, _ := tx.CreateBucketIfNotExists([]byte("state"))
			v := b.Get([]byte("QueryCounter"))
			if v != nil {
				training.QueryCounter = binary.BigEndian.Uint64(v)
			}
			v = b.Get([]byte("AbnormalCounter"))
			if v != nil {
				training.AbnormalCounter = binary.BigEndian.Uint64(v)
			}
			return nil
		})
	}

	if config.Config.SyncInterval != 0 {
		training.DBCon.NoSync = true
		ticker := time.NewTicker(config.Config.SyncInterval)
		go func() {
			for range ticker.C {
				training.DBCon.Sync()
			}
		}()
	}
}

func closeHandlers() {
	if training.DBCon != nil {
		training.DBCon.Update(func(tx *bolt.Tx) error {
			//Supplied value must remain valid for the life of the transaction
			qCount := make([]byte, 8)
			abCount := make([]byte, 8)

			b := tx.Bucket([]byte("state"))
			binary.BigEndian.PutUint64(qCount, training.QueryCounter)
			b.Put([]byte("QueryCounter"), qCount)

			binary.BigEndian.PutUint64(abCount, training.AbnormalCounter)
			b.Put([]byte("AbnormalCounter"), abCount)

			return nil
		})
		training.DBCon.Sync()
		training.DBCon.Close()
	}
	if logger.Output != nil {
		logger.Output.Close()
	}
}

//catching Interrupts
func signalHandler() {
	term := make(chan os.Signal)
	signal.Notify(term, os.Interrupt)
	<-term
	logger.Info("Shutting down...")
	//Closing open handler politely
	closeHandlers()
}

//initLogging redirect log output to file/stdout/stderr
func initLogging() {
	err := logger.Init(config.Config.LogPath, config.Config.LogLevel)
	if err != nil {
		panic(err)
	}
}

//maps database name to corresponding struct
func dbNameToStruct(db string) (d uint, err error) {
	switch strings.ToLower(db) {
	case "db2":
		d = db2
	case "mssql":
		d = mssql
	case "mysql", "mariadb":
		d = mysql
	case "oracle":
		d = oracle
	case "postgres":
		d = postgres
	default:
		err = fmt.Errorf("Unknown DBMS: %s", db)
	}
	return
}

//generateDBMS instantiate a new instance of DBMS
func generateDBMS() (utils.DBMS, func(io.Reader) ([]byte, error)) {
	switch config.Config.DB {
	case mssql:
		return new(dbms.MSSQL), dbms.MSSQLReadPacket
	case mysql:
		return new(dbms.MySQL), dbms.MySQLReadPacket
	case postgres:
		return new(dbms.Postgres), dbms.ReadPacket //TODO: implement explicit reader
	case oracle:
		return new(dbms.Oracle), dbms.ReadPacket //TODO: implement explicit reader
	case db2:
		return new(dbms.DB2), dbms.ReadPacket //TODO: implement explicit reader
	default:
		return nil, nil
	}
}

func handleClient(listenConn net.Conn, serverAddr *net.TCPAddr) error {
	d, reader := generateDBMS()
	logger.Debugf("Connected from: %s", listenConn.RemoteAddr())
	serverConn, err := net.DialTCP("tcp", nil, serverAddr)
	if err != nil {
		logger.Warning(err)
		listenConn.Close()
		return err
	}
	if config.Config.Timeout > 0 {
		if err = listenConn.SetDeadline(time.Now().Add(config.Config.Timeout)); err != nil {
			return err
		}
		if err = serverConn.SetDeadline(time.Now().Add(config.Config.Timeout)); err != nil {
			return err
		}
	}
	logger.Debugf("Connected to: %s", serverConn.RemoteAddr())
	d.SetSockets(listenConn, serverConn)
	d.SetCertificate(config.Config.TLSCertificate, config.Config.TLSPrivateKey)
	d.SetReader(reader)
	err = d.Handler()
	if err != nil {
		logger.Warning(err)
	}
	return err
}
<|endoftext|>


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

package x509

// Possible certificate files; stop after finding one.
var certFiles = []string{
	"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
	"/etc/pki/tls/certs/ca-bundle.crt",   // Fedora/RHEL
	"/etc/ssl/ca-bundle.pem",             // OpenSUSE
	"/etc/pki/tls/cacert.pem",            // OpenELEC
}
<commit_msg>crypto/x509: support RHEL 7 cert bundle<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package x509

// Possible certificate files; stop after finding one.
var certFiles = []string{
	"/etc/ssl/certs/ca-certificates.crt",                // Debian/Ubuntu/Gentoo etc.
	"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
	"/etc/pki/tls/certs/ca-bundle.crt",                  // Fedora/RHEL 6
	"/etc/ssl/ca-bundle.pem",                            // OpenSUSE
	"/etc/pki/tls/cacert.pem",                           // OpenELEC
}
<|endoftext|>


<commit_before>// Copyright 2014 The ezgliding Authors.
//
// This file is part of ezgliding.
//
// ezgliding is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ezgliding is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ezgliding.  If not, see <http://www.gnu.org/licenses/>.
//
// Author: Ricardo Rocha <rocha.porto@gmail.com>

package spatial

import (
	"reflect"
	"testing"
)

type DMS2DecimalTest struct {
	t  string
	in string
	r  float64
}

var dms2DecimalTests = []DMS2DecimalTest{
	{
		"latitude north conversion",
		"N323200",
		32.53333333333333,
	},
	{
		"latitude south conversion",
		"S323200",
		-32.53333333333333,
	},
	{
		"longitude east conversion",
		"E1002233",
		100.37583333333333,
	},
	{
		"longitude west conversion",
		"W1002233",
		-100.37583333333333,
	},
}

func TestDMS2Decimal(t *testing.T) {
	for _, test := range dms2DecimalTests {
		result := DMS2Decimal(test.in)
		if result != test.r {
			t.Errorf("test %v failed, expected %v got %v", test.t, test.r, result)
			continue
		}
	}
}

type DMD2DecimalTest struct {
	t  string
	in string
	r  float64
}

var dmd2DecimalTests = []DMD2DecimalTest{
	{
		"latitude north conversion",
		"N4616018",
		46.26696666666667,
	},
	{
		"latitude north conversion inverted",
		"4616018N",
		46.26696666666667,
	},
	{
		"latitude south conversion",
		"S4616018",
		-46.26696666666667,
	},
	{
		"latitude south conversion inverted",
		"4616018S",
		-46.26696666666667,
	},
	{
		"longitude east conversion",
		"E00627679",
		6.461316666666667,
	},
	{
		"longitude east conversion inverted",
		"00627679E",
		6.461316666666667,
	},
	{
		"longitude west conversion",
		"W00627679",
		-6.461316666666667,
	},
	{
		"longitude west conversion inverted",
		"00627679W",
		-6.461316666666667,
	},
}

func TestDMD2Decimal(t *testing.T) {
	for _, test := range dmd2DecimalTests {
		result := DMD2Decimal(test.in)
		if result != test.r {
			t.Errorf("test %v failed, expected %v got %v", test.t, test.r, result)
			continue
		}
	}
}
<commit_msg>drop reflect from spatial test<commit_after>// Copyright 2014 The ezgliding Authors.
//
// This file is part of ezgliding.
//
// ezgliding is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ezgliding is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ezgliding.  If not, see <http://www.gnu.org/licenses/>.
//
// Author: Ricardo Rocha <rocha.porto@gmail.com>

package spatial

import (
	"testing"
)

type DMS2DecimalTest struct {
	t  string
	in string
	r  float64
}

var dms2DecimalTests = []DMS2DecimalTest{
	{
		"latitude north conversion",
		"N323200",
		32.53333333333333,
	},
	{
		"latitude south conversion",
		"S323200",
		-32.53333333333333,
	},
	{
		"longitude east conversion",
		"E1002233",
		100.37583333333333,
	},
	{
		"longitude west conversion",
		"W1002233",
		-100.37583333333333,
	},
}

func TestDMS2Decimal(t *testing.T) {
	for _, test := range dms2DecimalTests {
		result := DMS2Decimal(test.in)
		if result != test.r {
			t.Errorf("test %v failed, expected %v got %v", test.t, test.r, result)
			continue
		}
	}
}

type DMD2DecimalTest struct {
	t  string
	in string
	r  float64
}

var dmd2DecimalTests = []DMD2DecimalTest{
	{
		"latitude north conversion",
		"N4616018",
		46.26696666666667,
	},
	{
		"latitude north conversion inverted",
		"4616018N",
		46.26696666666667,
	},
	{
		"latitude south conversion",
		"S4616018",
		-46.26696666666667,
	},
	{
		"latitude south conversion inverted",
		"4616018S",
		-46.26696666666667,
	},
	{
		"longitude east conversion",
		"E00627679",
		6.461316666666667,
	},
	{
		"longitude east conversion inverted",
		"00627679E",
		6.461316666666667,
	},
	{
		"longitude west conversion",
		"W00627679",
		-6.461316666666667,
	},
	{
		"longitude west conversion inverted",
		"00627679W",
		-6.461316666666667,
	},
}

func TestDMD2Decimal(t *testing.T) {
	for _, test := range dmd2DecimalTests {
		result := DMD2Decimal(test.in)
		if result != test.r {
			t.Errorf("test %v failed, expected %v got %v", test.t, test.r, result)
			continue
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Caleb Brose, Chris Fogerty, Rob Sheehy, Zach Taylor, Nick Miller
//
// 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 main

import (
    "fmt"
    "flag"
    "log"
    "net/http"
    "encoding/json"
    "io/ioutil"
    "strings"

    "github.com/mgutz/ansi"

    "github.com/zenazn/goji/web"
    "github.com/zenazn/goji/graceful"
    "github.com/zenazn/goji/web/middleware"

    "github.com/lighthouse/beacon/auth"
    "github.com/lighthouse/beacon/drivers"
    "github.com/lighthouse/beacon/structs"
)

var pemFile = flag.String("pem", "", "Path to Cert file")
var keyFile = flag.String("key", "", "Path to Key file")
var address = flag.String("h", "127.0.0.1:5000", "Address to host under")

var App *web.Mux
var Driver *structs.Driver

func init() {
    App = web.New()
    App.Use(middleware.Logger)
    App.Use(auth.Middleware)

    App.Handle("/d/*", func(c web.C, w http.ResponseWriter, r *http.Request) {
        target := fmt.Sprintf("http://%s",
            strings.SplitN(r.URL.String(), "/", 3)[2])

        req, err := http.NewRequest(r.Method, target, r.Body)
        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        contentType := r.Header.Get("Content-Type")
        if contentType != "" {
            req.Header.Set("Content-Type", contentType)
        }

        resp, err := http.DefaultClient.Do(req)

        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        body, err := ioutil.ReadAll(resp.Body)

        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        w.WriteHeader(resp.StatusCode)
        w.Write(body)
    })

    App.Get("/vms", func(c web.C, w http.ResponseWriter, r *http.Request) {
        response, _ := json.Marshal(Driver.GetVMs())
        w.Write(response)
    })

    App.Get("/which", func(c web.C, w http.ResponseWriter, r *http.Request) {
        response, _ := json.Marshal(Driver.Name)
        w.Write(response)
    })

    App.Compile()
}

func main() {
    log.Printf(ansi.Color("Starting Beacon...", "white+b"))

    if !flag.Parsed() {
        flag.Parse()
    }

    Driver = drivers.Decide()

    log.Printf("Provider Interface: %s\n", ansi.Color(Driver.Name, "cyan+b"))
    log.Printf("Authentication Token: %s\n", ansi.Color(*auth.Token, "cyan+b"))

    graceful.HandleSignals()

    graceful.PreHook(func() {
        log.Printf(ansi.Color("Gracefully Shutting Down...", "white+b"))
    })
    graceful.PostHook(func() {
        log.Printf(ansi.Color("Done!", "white+b"))
    })

    defer graceful.Wait()

    http.Handle("/", App)
    log.Printf("Listening on %s", *address)

    var err error

    if *pemFile != "" && *keyFile != "" {
        log.Printf("Setting up secure server...")
        err = graceful.ListenAndServeTLS(*address, *pemFile, *keyFile, http.DefaultServeMux)
    } else {
        log.Printf(ansi.Color("Setting up unsecure server...", "yellow+b"))
        err = graceful.ListenAndServe(*address, http.DefaultServeMux)
    }

    if err != nil {
        log.Fatal(err)
    }
}
<commit_msg>Experiment with possible solutions for streaming<commit_after>// Copyright 2014 Caleb Brose, Chris Fogerty, Rob Sheehy, Zach Taylor, Nick Miller
//
// 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 main

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

    "github.com/mgutz/ansi"

    "github.com/zenazn/goji/web"
    "github.com/zenazn/goji/graceful"
    "github.com/zenazn/goji/web/middleware"

    "github.com/lighthouse/beacon/auth"
    "github.com/lighthouse/beacon/drivers"
    "github.com/lighthouse/beacon/structs"
)

var pemFile = flag.String("pem", "", "Path to Cert file")
var keyFile = flag.String("key", "", "Path to Key file")
var address = flag.String("h", "127.0.0.1:5000", "Address to host under")

var App *web.Mux
var Driver *structs.Driver

func init() {
    App = web.New()
    App.Use(middleware.Logger)
    App.Use(auth.Middleware)

    App.Handle("/d/*", func(c web.C, w http.ResponseWriter, r *http.Request) {
        target := fmt.Sprintf("http://%s",
            strings.SplitN(r.URL.String(), "/", 3)[2])

        req, err := http.NewRequest(r.Method, target, r.Body)
        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        contentType := r.Header.Get("Content-Type")
        if contentType != "" {
            req.Header.Set("Content-Type", contentType)
        }

        resp, err := http.DefaultClient.Do(req)
        defer resp.Body.Close()

        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        w.WriteHeader(resp.StatusCode)
        var bodyBuffer = make([]byte, 2048)

        for {
            n, err := resp.Body.Read(bodyBuffer)
            w.Write(bodyBuffer[:n])

            if err != nil {
                break
            }
        }
    })

    App.Get("/vms", func(c web.C, w http.ResponseWriter, r *http.Request) {
        response, _ := json.Marshal(Driver.GetVMs())
        w.Write(response)
    })

    App.Get("/which", func(c web.C, w http.ResponseWriter, r *http.Request) {
        response, _ := json.Marshal(Driver.Name)
        w.Write(response)
    })

    App.Compile()
}

func main() {
    log.Printf(ansi.Color("Starting Beacon...", "white+b"))

    if !flag.Parsed() {
        flag.Parse()
    }

    Driver = drivers.Decide()

    log.Printf("Provider Interface: %s\n", ansi.Color(Driver.Name, "cyan+b"))
    log.Printf("Authentication Token: %s\n", ansi.Color(*auth.Token, "cyan+b"))

    graceful.HandleSignals()

    graceful.PreHook(func() {
        log.Printf(ansi.Color("Gracefully Shutting Down...", "white+b"))
    })
    graceful.PostHook(func() {
        log.Printf(ansi.Color("Done!", "white+b"))
    })

    defer graceful.Wait()

    http.Handle("/", App)
    log.Printf("Listening on %s", *address)

    var err error

    if *pemFile != "" && *keyFile != "" {
        log.Printf("Setting up secure server...")
        err = graceful.ListenAndServeTLS(*address, *pemFile, *keyFile, http.DefaultServeMux)
    } else {
        log.Printf(ansi.Color("Setting up unsecure server...", "yellow+b"))
        err = graceful.ListenAndServe(*address, http.DefaultServeMux)
    }

    if err != nil {
        log.Fatal(err)
    }
}
<|endoftext|>


<commit_before>package filters

import (
	"reflect"
	"regexp"
	"strings"

	"fmt"

	d "github.com/appPlant/alpinepass/src/data"
	"github.com/appPlant/alpinepass/src/util"
	"github.com/fatih/structs"
)

//Separator is tha character used for separating filter keys and values.
const Separator string = "="

//PropertyFilter allows filtering a Config for the content of its properties.
type PropertyFilter struct {
	Slices []string
}

func (p PropertyFilter) filter(data d.Config) d.Config {
	verifyFlags(p.Slices) //TODO verify only once and not for every Config
	for i := 0; i < len(p.Slices); i++ {
		data = filterProperty(p.Slices[i], data)
	}
	return data
}

func filterProperty(property string, data d.Config) d.Config {
	var split = strings.Split(property, Separator)
	var key = split[0]
	var value = split[1]
	var regex = regexp.MustCompile(value)

	//TODO check that key exists in Config field

	t := reflect.ValueOf(data)

	field := ""
	for i := 0; i < t.NumField(); i++ {
		//fmt.Println(reflect.TypeOf(t).String())
		fieldName := t.Type().Field(i).Name
		//fmt.Println(reflect.TypeOf(t.FieldByName(fieldName)))
		if strings.ToLower(fieldName) == key {
			field = fieldName
		}
	}
	fieldValue := t.FieldByName(field).String()

	fmt.Print("### Type: ")
	fmt.Println(reflect.TypeOf(fieldValue))
	//fmt.Println(t.FieldByName(field).Type().String())
	if reflect.TypeOf(fieldValue).String() == "string" {
		fmt.Println("### Filtering a string!")
	}
	if t.FieldByName(field).Type().String() == "[]string" {
		fmt.Println("### Filtering a list!")
	}
	/*
		if reflect.TypeOf(fieldValue).String() == "[]" {
			fmt.Println(fieldValue + " is a list!")
		}
	*/

	if !regex.MatchString(fieldValue) {
		data.IsValid = false
	}
	return data
}

func filterSingleProperty() {
}

func filterListProperty() {

}

//verifyFlags checks that the input flags are valid.
func verifyFlags(flags []string) {
	for i := 0; i < len(flags); i++ {
		flag := flags[i]

		//Do some simple checks.
		if !strings.Contains(flag, Separator) {
			util.ThrowError("The filter does not contain '" + Separator + "'! Flag: " + flag)
		}
		if strings.Count(flag, Separator) > 1 {
			util.ThrowError("The filter contains too many '" + Separator + "'! Flag: " + flag)
		}

		//check that the key part of a flag matches the fields available in struct Config.
		data := d.Config{}
		fieldNames := structs.Names(data)
		key := strings.ToLower(strings.Split(flag, Separator)[0])
		isContained := false
		for j := 0; j < len(fieldNames); j++ {
			if key == strings.ToLower(fieldNames[j]) {
				isContained = true
			}
		}
		if !isContained {
			util.ThrowError("The filter type is not valid! Flag: " + flag)
		}
	}
}
<commit_msg>Getting closer to making reflection work<commit_after>package filters

import (
	"reflect"
	"regexp"
	"strings"

	d "github.com/appPlant/alpinepass/src/data"
	"github.com/appPlant/alpinepass/src/util"
	"github.com/fatih/structs"
)

//Separator is tha character used for separating filter keys and values.
const Separator string = "="

//PropertyFilter allows filtering a Config for the content of its properties.
type PropertyFilter struct {
	Slices []string
}

func (p PropertyFilter) filter(data d.Config) d.Config {
	verifyFlags(p.Slices) //TODO verify only once and not for every Config
	for i := 0; i < len(p.Slices); i++ {
		data = filterProperty(p.Slices[i], data)
	}
	return data
}

func filterProperty(property string, data d.Config) d.Config {
	var split = strings.Split(property, Separator)
	var key = split[0]
	var value = split[1]
	var regex = regexp.MustCompile(value)

	//TODO check that key exists in Config field

	t := reflect.ValueOf(data)

	field := ""
	for i := 0; i < t.NumField(); i++ {
		fieldName := t.Type().Field(i).Name
		if strings.ToLower(fieldName) == key {
			field = fieldName
		}
	}
	fieldValue := t.FieldByName(field).String()

	//fmt.Print("### Type: ")
	//fmt.Println(reflect.TypeOf(fieldValue))
	//fmt.Println(t.FieldByName(field).Type().String())
	if reflect.TypeOf(fieldValue).String() == "string" {
		if t.FieldByName(field).Type().String() == "[]string" {
			//fmt.Println("### Filtering a list!")
		} else {
			//fmt.Println("### Filtering a string!")
			if !regex.MatchString(fieldValue) {
				data.IsValid = false
			}
		}
	}

	return data
}

//verifyFlags checks that the input flags are valid.
func verifyFlags(flags []string) {
	for i := 0; i < len(flags); i++ {
		flag := flags[i]

		//Do some simple checks.
		if !strings.Contains(flag, Separator) {
			util.ThrowError("The filter does not contain '" + Separator + "'! Flag: " + flag)
		}
		if strings.Count(flag, Separator) > 1 {
			util.ThrowError("The filter contains too many '" + Separator + "'! Flag: " + flag)
		}

		//Check that the key part of a flag matches the fields available in struct Config.
		data := d.Config{}
		fieldNames := structs.Names(data)
		key := strings.ToLower(strings.Split(flag, Separator)[0])
		isContained := false
		for j := 0; j < len(fieldNames); j++ {
			if key == strings.ToLower(fieldNames[j]) {
				isContained = true
			}
		}
		if !isContained {
			util.ThrowError("The filter type is not valid! Flag: " + flag)
		}
	}
}
<|endoftext|>


<commit_before>package echo

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/webx-top/webx/lib/tagfast"
)

var DefaultHtmlFilter = func(v string) (r string) {
	return v
}

type binder struct {
	*Echo
}

func (a binder) Bind(r *http.Request, i interface{}) (err error) {
	ct := r.Header.Get(ContentType)
	err = UnsupportedMediaType
	if strings.HasPrefix(ct, ApplicationJSON) {
		err = json.NewDecoder(r.Body).Decode(i)
	} else if strings.HasPrefix(ct, ApplicationXML) {
		err = xml.NewDecoder(r.Body).Decode(i)
	} else if strings.Contains(ct, MultipartForm) {
		err = a.structMap(i, r)
	}
	return
}

// StructMap function mapping params to controller's properties
func (a binder) structMap(m interface{}, r *http.Request) error {
	return NamedStructMap(a.Echo, m, r, "")
}

// user[name][test]
func SplitJson(s string) ([]string, error) {
	res := make([]string, 0)
	var begin, end int
	var isleft bool
	for i, r := range s {
		switch r {
		case '[':
			isleft = true
			if i > 0 && s[i-1] != ']' {
				if begin == end {
					return nil, errors.New("unknow character")
				}
				res = append(res, s[begin:end+1])
			}
			begin = i + 1
			end = begin
		case ']':
			if !isleft {
				return nil, errors.New("unknow character")
			}
			isleft = false
			if begin != end {
				//return nil, errors.New("unknow character")

				res = append(res, s[begin:end+1])
				begin = i + 1
				end = begin
			}
		default:
			end = i
		}
		if i == len(s)-1 && begin != end {
			res = append(res, s[begin:end+1])
		}
	}
	return res, nil
}

func NamedStructMap(e *Echo, m interface{}, r *http.Request, topName string) error {

	vc := reflect.ValueOf(m)
	tc := reflect.TypeOf(m)

	switch tc.Kind() {
	case reflect.Struct:
	case reflect.Ptr:
		vc = vc.Elem()
		tc = tc.Elem()
	}

	for k, t := range r.Form {

		if k == "" || k[0] == '_' {
			continue
		}

		if topName != "" {
			if !strings.HasPrefix(k, topName) {
				continue
			}
			k = k[len(topName)+1:]
		}

		v := t[0]
		names := strings.Split(k, ".")
		var err error
		length := len(names)
		if length == 1 {
			names, err = SplitJson(k)
			if err != nil {
				e.Logger().Warn("Unrecognize form key %v %v", k, err)
				continue
			}
		}
		length = len(names)
		var value reflect.Value = vc
		for i, name := range names {
			name = strings.Title(name)

			//不是最后一个元素
			if i != length-1 {
				if value.Kind() != reflect.Struct {
					e.Logger().Warn("arg error, value kind is %v", value.Kind())
					break
				}
				value = value.FieldByName(name)
				if !value.IsValid() {
					e.Logger().Warn("(%v value is not valid %v)", name, value)
					break
				}
				if !value.CanSet() {
					e.Logger().Warn("can not set %v -> %v", name, value.Interface())
					break
				}
				f, _ := value.Type().FieldByName(name)
				if tagfast.Value(tc, f, "form_options") == "-" {
					continue
				}
				if value.Kind() == reflect.Ptr {
					if value.IsNil() {
						value.Set(reflect.New(value.Type().Elem()))
					}
					value = value.Elem()
				}
			} else {
				if value.Kind() != reflect.Struct {
					e.Logger().Warn("arg error, value %v kind is %v", name, value.Kind())
					break
				}
				tv := value.FieldByName(name)
				if !tv.IsValid() {
					break
				}
				if !tv.CanSet() {
					e.Logger().Warn("can not set %v to %v", k, tv)
					break
				}
				f, _ := tv.Type().FieldByName(name)
				if tagfast.Value(tc, f, "form_options") == "-" {
					continue
				}
				if tv.Kind() == reflect.Ptr {
					tv.Set(reflect.New(tv.Type().Elem()))
					tv = tv.Elem()
				}

				var l interface{}
				switch k := tv.Kind(); k {
				case reflect.String:
					switch tagfast.Value(tc, f, "form_filter") {
					case "html":
						v = DefaultHtmlFilter(v)
					}
					l = v
					tv.Set(reflect.ValueOf(l))
				case reflect.Bool:
					l = (v != "false" && v != "0")
					tv.Set(reflect.ValueOf(l))
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
					x, err := strconv.Atoi(v)
					if err != nil {
						e.Logger().Warn("arg %v as int: %v", v, err)
						break
					}
					l = x
					tv.Set(reflect.ValueOf(l))
				case reflect.Int64:
					x, err := strconv.ParseInt(v, 10, 64)
					if err != nil {
						e.Logger().Warn("arg %v as int64: %v", v, err)
						break
					}
					l = x
					tv.Set(reflect.ValueOf(l))
				case reflect.Float32, reflect.Float64:
					x, err := strconv.ParseFloat(v, 64)
					if err != nil {
						e.Logger().Warn("arg %v as float64: %v", v, err)
						break
					}
					l = x
					tv.Set(reflect.ValueOf(l))
				case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
					x, err := strconv.ParseUint(v, 10, 64)
					if err != nil {
						e.Logger().Warn("arg %v as uint: %v", v, err)
						break
					}
					l = x
					tv.Set(reflect.ValueOf(l))
				case reflect.Struct:
					if tvf, ok := tv.Interface().(FromConversion); ok {
						err := tvf.FromString(v)
						if err != nil {
							e.Logger().Warn("struct %v invoke FromString faild", tvf)
						}
					} else if tv.Type().String() == "time.Time" {
						x, err := time.Parse("2006-01-02 15:04:05.000 -0700", v)
						if err != nil {
							x, err = time.Parse("2006-01-02 15:04:05", v)
							if err != nil {
								x, err = time.Parse("2006-01-02", v)
								if err != nil {
									e.Logger().Warn("unsupported time format %v, %v", v, err)
									break
								}
							}
						}
						l = x
						tv.Set(reflect.ValueOf(l))
					} else {
						e.Logger().Warn("can not set an struct which is not implement Fromconversion interface")
					}
				case reflect.Ptr:
					e.Logger().Warn("can not set an ptr of ptr")
				case reflect.Slice, reflect.Array:
					tt := tv.Type().Elem()
					tk := tt.Kind()

					if tv.IsNil() {
						tv.Set(reflect.MakeSlice(tv.Type(), len(t), len(t)))
					}

					for i, s := range t {
						var err error
						switch tk {
						case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int8, reflect.Int64:
							var v int64
							v, err = strconv.ParseInt(s, 10, tt.Bits())
							if err == nil {
								tv.Index(i).SetInt(v)
							}
						case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
							var v uint64
							v, err = strconv.ParseUint(s, 10, tt.Bits())
							if err == nil {
								tv.Index(i).SetUint(v)
							}
						case reflect.Float32, reflect.Float64:
							var v float64
							v, err = strconv.ParseFloat(s, tt.Bits())
							if err == nil {
								tv.Index(i).SetFloat(v)
							}
						case reflect.Bool:
							var v bool
							v, err = strconv.ParseBool(s)
							if err == nil {
								tv.Index(i).SetBool(v)
							}
						case reflect.String:
							tv.Index(i).SetString(s)
						case reflect.Complex64, reflect.Complex128:
							// TODO:
							err = fmt.Errorf("unsupported slice element type %v", tk.String())
						default:
							err = fmt.Errorf("unsupported slice element type %v", tk.String())
						}
						if err != nil {
							e.Logger().Warn("slice error: %v, %v", name, err)
							break
						}
					}
				default:
					break
				}
			}
		}
	}
	return nil
}

// a struct implements this interface can be convert from request param to a struct
type FromConversion interface {
	FromString(content string) error
}

// a struct implements this interface can be convert from struct to template variable
// Not Implemented
type ToConversion interface {
	ToString() string
}
<commit_msg>update<commit_after>package echo

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/webx-top/webx/lib/tagfast"
)

var DefaultHtmlFilter = func(v string) (r string) {
	return v
}

type binder struct {
	*Echo
}

func (a binder) Bind(r *http.Request, i interface{}) (err error) {
	ct := r.Header.Get(ContentType)
	err = UnsupportedMediaType
	if strings.HasPrefix(ct, ApplicationJSON) {
		err = json.NewDecoder(r.Body).Decode(i)
	} else if strings.HasPrefix(ct, ApplicationXML) {
		err = xml.NewDecoder(r.Body).Decode(i)
	} else if strings.Contains(ct, MultipartForm) {
		err = a.structMap(i, r)
	}
	return
}

// StructMap function mapping params to controller's properties
func (a binder) structMap(m interface{}, r *http.Request) error {
	return NamedStructMap(a.Echo, m, r, "")
}

// user[name][test]
func SplitJson(s string) ([]string, error) {
	res := make([]string, 0)
	var begin, end int
	var isleft bool
	for i, r := range s {
		switch r {
		case '[':
			isleft = true
			if i > 0 && s[i-1] != ']' {
				if begin == end {
					return nil, errors.New("unknow character")
				}
				res = append(res, s[begin:end+1])
			}
			begin = i + 1
			end = begin
		case ']':
			if !isleft {
				return nil, errors.New("unknow character")
			}
			isleft = false
			if begin != end {
				//return nil, errors.New("unknow character")

				res = append(res, s[begin:end+1])
				begin = i + 1
				end = begin
			}
		default:
			end = i
		}
		if i == len(s)-1 && begin != end {
			res = append(res, s[begin:end+1])
		}
	}
	return res, nil
}

func NamedStructMap(e *Echo, m interface{}, r *http.Request, topName string) error {
	if r.Form == nil {
		r.ParseForm()
	}
	vc := reflect.ValueOf(m)
	tc := reflect.TypeOf(m)

	switch tc.Kind() {
	case reflect.Struct:
	case reflect.Ptr:
		vc = vc.Elem()
		tc = tc.Elem()
	}

	for k, t := range r.Form {

		if k == "" || k[0] == '_' {
			continue
		}

		if topName != "" {
			if !strings.HasPrefix(k, topName) {
				continue
			}
			k = k[len(topName)+1:]
		}

		v := t[0]
		names := strings.Split(k, ".")
		var err error
		length := len(names)
		if length == 1 {
			names, err = SplitJson(k)
			if err != nil {
				e.Logger().Warn("Unrecognize form key %v %v", k, err)
				continue
			}
		}
		length = len(names)
		var value reflect.Value = vc
		for i, name := range names {
			name = strings.Title(name)

			//不是最后一个元素
			if i != length-1 {
				if value.Kind() != reflect.Struct {
					e.Logger().Warn("arg error, value kind is %v", value.Kind())
					break
				}
				value = value.FieldByName(name)
				if !value.IsValid() {
					e.Logger().Warn("(%v value is not valid %v)", name, value)
					break
				}
				if !value.CanSet() {
					e.Logger().Warn("can not set %v -> %v", name, value.Interface())
					break
				}
				f, _ := value.Type().FieldByName(name)
				if tagfast.Value(tc, f, "form_options") == "-" {
					continue
				}
				if value.Kind() == reflect.Ptr {
					if value.IsNil() {
						value.Set(reflect.New(value.Type().Elem()))
					}
					value = value.Elem()
				}
			} else {
				if value.Kind() != reflect.Struct {
					e.Logger().Warn("arg error, value %v kind is %v", name, value.Kind())
					break
				}
				tv := value.FieldByName(name)
				if !tv.IsValid() {
					break
				}
				if !tv.CanSet() {
					e.Logger().Warn("can not set %v to %v", k, tv)
					break
				}
				f, _ := tv.Type().FieldByName(name)
				if tagfast.Value(tc, f, "form_options") == "-" {
					continue
				}
				if tv.Kind() == reflect.Ptr {
					tv.Set(reflect.New(tv.Type().Elem()))
					tv = tv.Elem()
				}

				var l interface{}
				switch k := tv.Kind(); k {
				case reflect.String:
					switch tagfast.Value(tc, f, "form_filter") {
					case "html":
						v = DefaultHtmlFilter(v)
					}
					l = v
					tv.Set(reflect.ValueOf(l))
				case reflect.Bool:
					l = (v != "false" && v != "0")
					tv.Set(reflect.ValueOf(l))
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
					x, err := strconv.Atoi(v)
					if err != nil {
						e.Logger().Warn("arg %v as int: %v", v, err)
						break
					}
					l = x
					tv.Set(reflect.ValueOf(l))
				case reflect.Int64:
					x, err := strconv.ParseInt(v, 10, 64)
					if err != nil {
						e.Logger().Warn("arg %v as int64: %v", v, err)
						break
					}
					l = x
					tv.Set(reflect.ValueOf(l))
				case reflect.Float32, reflect.Float64:
					x, err := strconv.ParseFloat(v, 64)
					if err != nil {
						e.Logger().Warn("arg %v as float64: %v", v, err)
						break
					}
					l = x
					tv.Set(reflect.ValueOf(l))
				case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
					x, err := strconv.ParseUint(v, 10, 64)
					if err != nil {
						e.Logger().Warn("arg %v as uint: %v", v, err)
						break
					}
					l = x
					tv.Set(reflect.ValueOf(l))
				case reflect.Struct:
					if tvf, ok := tv.Interface().(FromConversion); ok {
						err := tvf.FromString(v)
						if err != nil {
							e.Logger().Warn("struct %v invoke FromString faild", tvf)
						}
					} else if tv.Type().String() == "time.Time" {
						x, err := time.Parse("2006-01-02 15:04:05.000 -0700", v)
						if err != nil {
							x, err = time.Parse("2006-01-02 15:04:05", v)
							if err != nil {
								x, err = time.Parse("2006-01-02", v)
								if err != nil {
									e.Logger().Warn("unsupported time format %v, %v", v, err)
									break
								}
							}
						}
						l = x
						tv.Set(reflect.ValueOf(l))
					} else {
						e.Logger().Warn("can not set an struct which is not implement Fromconversion interface")
					}
				case reflect.Ptr:
					e.Logger().Warn("can not set an ptr of ptr")
				case reflect.Slice, reflect.Array:
					tt := tv.Type().Elem()
					tk := tt.Kind()

					if tv.IsNil() {
						tv.Set(reflect.MakeSlice(tv.Type(), len(t), len(t)))
					}

					for i, s := range t {
						var err error
						switch tk {
						case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int8, reflect.Int64:
							var v int64
							v, err = strconv.ParseInt(s, 10, tt.Bits())
							if err == nil {
								tv.Index(i).SetInt(v)
							}
						case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
							var v uint64
							v, err = strconv.ParseUint(s, 10, tt.Bits())
							if err == nil {
								tv.Index(i).SetUint(v)
							}
						case reflect.Float32, reflect.Float64:
							var v float64
							v, err = strconv.ParseFloat(s, tt.Bits())
							if err == nil {
								tv.Index(i).SetFloat(v)
							}
						case reflect.Bool:
							var v bool
							v, err = strconv.ParseBool(s)
							if err == nil {
								tv.Index(i).SetBool(v)
							}
						case reflect.String:
							tv.Index(i).SetString(s)
						case reflect.Complex64, reflect.Complex128:
							// TODO:
							err = fmt.Errorf("unsupported slice element type %v", tk.String())
						default:
							err = fmt.Errorf("unsupported slice element type %v", tk.String())
						}
						if err != nil {
							e.Logger().Warn("slice error: %v, %v", name, err)
							break
						}
					}
				default:
					break
				}
			}
		}
	}
	return nil
}

// a struct implements this interface can be convert from request param to a struct
type FromConversion interface {
	FromString(content string) error
}

// a struct implements this interface can be convert from struct to template variable
// Not Implemented
type ToConversion interface {
	ToString() string
}
<|endoftext|>


<commit_before>// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"encoding/csv"
	"fmt"
	"math"
	"os"
	"sort"

	"github.com/google/syzkaller/pkg/stats"
)

type Cell = interface{}

// All tables that syz-testbed generates have named columns and rows.
// Table type simplifies generation and processing of such tables.
type Table struct {
	TopLeftHeader string
	ColumnHeaders []string
	Cells         map[string]map[string]Cell
}

type ValueCell struct {
	Value         float64
	Sample        *stats.Sample
	PercentChange *float64
	PValue        *float64
}

func NewValueCell(sample *stats.Sample) *ValueCell {
	return &ValueCell{Value: sample.Median(), Sample: sample}
}

func (c *ValueCell) String() string {
	const fractionCutoff = 100
	if math.Abs(c.Value) < fractionCutoff {
		return fmt.Sprintf("%.1f", c.Value)
	}
	return fmt.Sprintf("%.0f", math.Round(c.Value))
}

func NewTable(topLeft string, columns ...string) *Table {
	return &Table{
		TopLeftHeader: topLeft,
		ColumnHeaders: columns,
	}
}

func (t *Table) Get(row, column string) Cell {
	if t.Cells == nil {
		return nil
	}
	rowMap := t.Cells[row]
	if rowMap == nil {
		return nil
	}
	return rowMap[column]
}

func (t *Table) Set(row, column string, value Cell) {
	if t.Cells == nil {
		t.Cells = make(map[string]map[string]Cell)
	}
	rowMap, ok := t.Cells[row]
	if !ok {
		rowMap = make(map[string]Cell)
		t.Cells[row] = rowMap
	}
	rowMap[column] = value
}

func (t *Table) AddColumn(column string) {
	t.ColumnHeaders = append(t.ColumnHeaders, column)
}

func (t *Table) AddRow(row string, cells ...Cell) {
	if len(cells) != len(t.ColumnHeaders) {
		panic("AddRow: the length of the row does not equal the number of columns")
	}
	for i, col := range t.ColumnHeaders {
		t.Set(row, col, cells[i])
	}
}

func (t *Table) SortedRows() []string {
	rows := []string{}
	for key := range t.Cells {
		rows = append(rows, key)
	}
	sort.Strings(rows)
	return rows
}

func (t *Table) ToStrings() [][]string {
	table := [][]string{}
	headers := append([]string{t.TopLeftHeader}, t.ColumnHeaders...)
	table = append(table, headers)
	if t.Cells != nil {
		rowHeaders := t.SortedRows()
		for _, row := range rowHeaders {
			tableRow := []string{row}
			for _, column := range t.ColumnHeaders {
				tableRow = append(tableRow, fmt.Sprintf("%s", t.Get(row, column)))
			}
			table = append(table, tableRow)
		}
	}
	return table
}

func (t *Table) SaveAsCsv(fileName string) error {
	f, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer f.Close()
	return csv.NewWriter(f).WriteAll(t.ToStrings())
}

func (t *Table) SetRelativeValues(baseColumn string) error {
	for rowName, row := range t.Cells {
		baseCell := t.Get(rowName, baseColumn)
		if baseCell == nil {
			return fmt.Errorf("base column %s not found in row %s", baseColumn, rowName)
		}
		baseValueCell, ok := baseCell.(*ValueCell)
		if !ok {
			return fmt.Errorf("base column cell is not a ValueCell, %T", baseCell)
		}
		baseSample := baseValueCell.Sample.RemoveOutliers()
		for column, cell := range row {
			if column == baseColumn {
				continue
			}
			valueCell, ok := cell.(*ValueCell)
			if !ok {
				continue
			}
			if baseValueCell.Value != 0 {
				valueDiff := valueCell.Value - baseValueCell.Value
				valueCell.PercentChange = new(float64)
				*valueCell.PercentChange = valueDiff / baseValueCell.Value * 100
			}

			cellSample := valueCell.Sample.RemoveOutliers()
			pval, err := stats.UTest(baseSample, cellSample)
			if err == nil {
				// Sometimes it fails because there are too few samples.
				valueCell.PValue = new(float64)
				*valueCell.PValue = pval
			}
		}
	}
	return nil
}
<commit_msg>tools/syz-testbed: add a special cell type for ratios<commit_after>// Copyright 2021 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"encoding/csv"
	"fmt"
	"math"
	"os"
	"sort"

	"github.com/google/syzkaller/pkg/stats"
)

type Cell = interface{}

// All tables that syz-testbed generates have named columns and rows.
// Table type simplifies generation and processing of such tables.
type Table struct {
	TopLeftHeader string
	ColumnHeaders []string
	Cells         map[string]map[string]Cell
}

type ValueCell struct {
	Value         float64
	Sample        *stats.Sample
	PercentChange *float64
	PValue        *float64
}

type RatioCell struct {
	TrueCount  int
	TotalCount int
}

func NewValueCell(sample *stats.Sample) *ValueCell {
	return &ValueCell{Value: sample.Median(), Sample: sample}
}

func (c *ValueCell) String() string {
	const fractionCutoff = 100
	if math.Abs(c.Value) < fractionCutoff {
		return fmt.Sprintf("%.1f", c.Value)
	}
	return fmt.Sprintf("%.0f", math.Round(c.Value))
}

func NewRatioCell(trueCount, totalCount int) *RatioCell {
	return &RatioCell{trueCount, totalCount}
}

func (c *RatioCell) String() string {
	return fmt.Sprintf("%d / %d", c.TrueCount, c.TotalCount)
}

func NewTable(topLeft string, columns ...string) *Table {
	return &Table{
		TopLeftHeader: topLeft,
		ColumnHeaders: columns,
	}
}

func (t *Table) Get(row, column string) Cell {
	if t.Cells == nil {
		return nil
	}
	rowMap := t.Cells[row]
	if rowMap == nil {
		return nil
	}
	return rowMap[column]
}

func (t *Table) Set(row, column string, value Cell) {
	if t.Cells == nil {
		t.Cells = make(map[string]map[string]Cell)
	}
	rowMap, ok := t.Cells[row]
	if !ok {
		rowMap = make(map[string]Cell)
		t.Cells[row] = rowMap
	}
	rowMap[column] = value
}

func (t *Table) AddColumn(column string) {
	t.ColumnHeaders = append(t.ColumnHeaders, column)
}

func (t *Table) AddRow(row string, cells ...Cell) {
	if len(cells) != len(t.ColumnHeaders) {
		panic("AddRow: the length of the row does not equal the number of columns")
	}
	for i, col := range t.ColumnHeaders {
		t.Set(row, col, cells[i])
	}
}

func (t *Table) SortedRows() []string {
	rows := []string{}
	for key := range t.Cells {
		rows = append(rows, key)
	}
	sort.Strings(rows)
	return rows
}

func (t *Table) ToStrings() [][]string {
	table := [][]string{}
	headers := append([]string{t.TopLeftHeader}, t.ColumnHeaders...)
	table = append(table, headers)
	if t.Cells != nil {
		rowHeaders := t.SortedRows()
		for _, row := range rowHeaders {
			tableRow := []string{row}
			for _, column := range t.ColumnHeaders {
				tableRow = append(tableRow, fmt.Sprintf("%s", t.Get(row, column)))
			}
			table = append(table, tableRow)
		}
	}
	return table
}

func (t *Table) SaveAsCsv(fileName string) error {
	f, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer f.Close()
	return csv.NewWriter(f).WriteAll(t.ToStrings())
}

func (t *Table) SetRelativeValues(baseColumn string) error {
	for rowName, row := range t.Cells {
		baseCell := t.Get(rowName, baseColumn)
		if baseCell == nil {
			return fmt.Errorf("base column %s not found in row %s", baseColumn, rowName)
		}
		baseValueCell, ok := baseCell.(*ValueCell)
		if !ok {
			return fmt.Errorf("base column cell is not a ValueCell, %T", baseCell)
		}
		baseSample := baseValueCell.Sample.RemoveOutliers()
		for column, cell := range row {
			if column == baseColumn {
				continue
			}
			valueCell, ok := cell.(*ValueCell)
			if !ok {
				continue
			}
			if baseValueCell.Value != 0 {
				valueDiff := valueCell.Value - baseValueCell.Value
				valueCell.PercentChange = new(float64)
				*valueCell.PercentChange = valueDiff / baseValueCell.Value * 100
			}

			cellSample := valueCell.Sample.RemoveOutliers()
			pval, err := stats.UTest(baseSample, cellSample)
			if err == nil {
				// Sometimes it fails because there are too few samples.
				valueCell.PValue = new(float64)
				*valueCell.PValue = pval
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Knative 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 testing

import (
	"context"

	"go.uber.org/zap"
	"go.uber.org/zap/zaptest"

	"knative.dev/pkg/logging"
)

// TestLogger gets a logger to use in unit and end to end tests
func TestLogger(t zaptest.TestingT) *zap.SugaredLogger {
	opts := zaptest.WrapOptions(
		zap.AddCaller(),
		zap.Development(),
	)

	return zaptest.NewLogger(t, opts).Sugar()
}

// ClearAll removes all the testing loggers.
// TODO(taragu) remove this after removing all ClearAll() calls from serving and eventing
func ClearAll() {}

// TestContextWithLogger returns a context with a logger to be used in tests
func TestContextWithLogger(t zaptest.TestingT) context.Context {
	return logging.WithLogger(context.Background(), TestLogger(t))
}
<commit_msg>Remove ClearAll from the codebase (#1657)<commit_after>/*
Copyright 2018 The Knative 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 testing

import (
	"context"

	"go.uber.org/zap"
	"go.uber.org/zap/zaptest"

	"knative.dev/pkg/logging"
)

// TestLogger gets a logger to use in unit and end to end tests
func TestLogger(t zaptest.TestingT) *zap.SugaredLogger {
	opts := zaptest.WrapOptions(
		zap.AddCaller(),
		zap.Development(),
	)

	return zaptest.NewLogger(t, opts).Sugar()
}

// TestContextWithLogger returns a context with a logger to be used in tests
func TestContextWithLogger(t zaptest.TestingT) context.Context {
	return logging.WithLogger(context.Background(), TestLogger(t))
}
<|endoftext|>


<commit_before>package rhynock

// A type to hold a message and the sender of that message
type Bottle struct {
	Sender *Connection
	Message []byte
}

// An interface to define a type that can recieve a bottle
// And can be told when a connection has been closed
type BottleDst interface {
	GetBottleChan() (chan *Bottle)
	ConnectionClosed(*Connection)
}
<commit_msg>Connection opened as well as closed requirements<commit_after>package rhynock

// A type to hold a message and the sender of that message
type Bottle struct {
	Sender *Connection
	Message []byte
}

// An interface to define a type that can recieve a bottle
// And can be told when a connection has been closed
type BottleDst interface {
	GetBottleChan() (chan *Bottle)
	ConnectionClosed(*Connection)
	ConnectionOpened(*Connection)
}
<|endoftext|>