<commit_before>package main

import (
  "fmt"
  "encoding/hex"
)

func main()  {
  byteres := make([]byte, 16)
  var mask byte = 0x01
  byteres[0] = 0x80
  byteres[0] |= mask << 2
  byteres[2] = mask
  fmt.Println(byteres)
  fmt.Println(hex.EncodeToString(byteres))

  bitArray,_ := NewBitAppendArray(64)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)

  fmt.Println(hex.EncodeToString(bitArray.returnArray()))

  // byteStruct := BitAppendArray{}
  // byteStruct.init(64)
  // fmt.Print(byteStruct.lengthStruct())
}

type BitAppendArray struct {
  arr []byte
  mask0 byte
  mask1 byte
  arrIdx int
  bitIdx uint
}

// Constructor for the BitAppendArray struct
//
// usage:
// bitArray := NewBitAppendArray(64)
func NewBitAppendArray(numBits int) (*BitAppendArray, error) {
  // return error here if numBits is not good

  return &BitAppendArray{
    arr: make([]byte, numBits / 8),
    mask0: 0x00,
    mask1: 0x01,
    arrIdx: 0,
    bitIdx: 7,
  }, nil
}

// Append a bit to the byte array from left to right
func (ds *BitAppendArray) appendBit(bit int) {
  switch bit {
    case 0:
      ds.arr[ds.arrIdx] |= ds.mask0 << ds.bitIdx
    case 1:
      ds.arr[ds.arrIdx] |= ds.mask1 << ds.bitIdx
  }

  if ds.bitIdx > 0 {
    ds.bitIdx--
  } else {
    // the last bit in the current byte has been set, so
    ds.arrIdx++
    ds.bitIdx = 7
    // do something once ds.arrIdx has reached it's max
  }
}

func (ds *BitAppendArray) returnArray() []byte {
  return ds.arr
}
<commit_msg>Finished AppendBit struct<commit_after>package main

import (
  "fmt"
  "errors"
  "encoding/hex"
)

func main()  {
  byteres := make([]byte, 16)
  var mask byte = 0x01
  byteres[0] = 0x80
  byteres[0] |= mask << 2
  byteres[2] = mask
  fmt.Println(byteres)
  fmt.Println(hex.EncodeToString(byteres))

  bitArray,_ := NewAppendBit(64)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(0)
  bitArray.appendBit(0)
  bitArray.appendBit(1)
  bitArray.appendBit(1)
  bitArray.appendBit(1)

  fmt.Println(hex.EncodeToString(bitArray.getArray()))
}

// Struct to simplify appending bits to a byte array,
// from left to right
type AppendBit struct {
  byteArray []byte
  max int
  mask0 byte
  mask1 byte
  arrayIdx int
  bitIdx uint
}

/**
 * Constructor for the AppendBit struct. It must be initialized
 * with a non-zero int that is a multiple of 8.
 * Usage:
 *    bitArray := NewAppendBit(64)
 *
 * @method NewAppendBit
 * @param  {int}        numBits The number of bits, as an int
 * @return {AppendBit}  The AppendBit struct
 * @return {error}      If there is an error
 */
func NewAppendBit(numBits int) (*AppendBit, error) {
  // If numBits is invalid
  if (numBits == 0) || (numBits % 8 != 0) {
    return nil, errors.New("'numBits' must be a non-zero multiple of 8")
  }

  return &AppendBit{
    byteArray: make([]byte, numBits / 8),
    max: numBits / 8,
    mask0: 0x00,
    mask1: 0x01,
    arrayIdx: 0,
    bitIdx: 7,
  }, nil
}

/**
 * Append a bit to the byte array from left to right
 * @method appendBit
 * @param  {int} bit  Append a one with '1', and zero with '0'
 */
func (ab *AppendBit) appendBit(bit int) error {
  if ab.arrayIdx == ab.max {
    return errors.New("Cannot contine to append to a full byteArray")
  }

  // Shift the 'mask' (bit of 1 or 0) by the proper amount to
  // fill the byte up from left to right.
  switch bit {
    case 0:
      ab.byteArray[ab.arrayIdx] |= ab.mask0 << ab.bitIdx
    case 1:
      ab.byteArray[ab.arrayIdx] |= ab.mask1 << ab.bitIdx
  }

  if ab.bitIdx > 0 {
    // Decrement the index into the current byte so the next
    // bit to be set will be on the right.
    ab.bitIdx--
  } else {
    // The last bit in the current byte has been set, so increment
    // the index into the byte array, and reset the bit index.
    ab.arrayIdx++
    ab.bitIdx = 7
  }

  return nil
}

/**
 * Returns the current byte array
 * @method getArray
 * @return {[]byte]}  The byte array
 */
func (ab AppendBit) getArray() []byte {
  return ab.byteArray
}
<|endoftext|>


<commit_before>package history

import (
	"bufio"
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/mattn/go-isatty"

	"../text"
)

var Mark = "!"

var DisableMarks = "\"'"

func (hisObj *Container) Replace(line string) (string, bool) {
	var mark rune
	for _, c := range Mark {
		mark = c
		break
	}

	var buffer bytes.Buffer
	isReplaced := false
	reader := strings.NewReader(line)
	history_count := hisObj.Len()

	quotedChar := '\000'

	for reader.Len() > 0 {
		ch, _, _ := reader.ReadRune()
		if quotedChar == '\000' && strings.IndexRune(DisableMarks, ch) >= 0 {
			quotedChar = ch
			buffer.WriteRune(ch)
			continue
		} else if ch == quotedChar {
			quotedChar = '\000'
			buffer.WriteRune(ch)
			continue
		}
		if ch != mark || reader.Len() <= 0 || quotedChar != '\000' {
			buffer.WriteRune(ch)
			continue
		}
		ch, _, _ = reader.ReadRune()
		if n := strings.IndexRune("^$:*", ch); n >= 0 {
			reader.UnreadRune()
			if history_count >= 1 {
				line := hisObj.At(history_count - 1)
				ExpandMacro(&buffer, reader, line)
				isReplaced = true
			}
			continue
		}
		if ch == mark { // !!
			if history_count >= 1 {
				line := hisObj.At(history_count - 1)
				ExpandMacro(&buffer, reader, line)
				isReplaced = true
				continue
			} else {
				buffer.WriteRune(mark)
				continue
			}
		}
		if strings.IndexRune("0123456789", ch) >= 0 { // !n
			reader.UnreadRune()
			var backno int
			fmt.Fscan(reader, &backno)
			backno = backno % history_count
			if 0 <= backno && backno < history_count {
				line := hisObj.At(backno)
				ExpandMacro(&buffer, reader, line)
				isReplaced = true
			}
			continue
		}
		if ch == '-' && reader.Len() > 0 { // !-n
			var number int
			if _, err := fmt.Fscan(reader, &number); err == nil {
				backno := history_count - number
				for backno < 0 {
					backno += history_count
				}
				if 0 <= backno && backno < history_count {
					line := hisObj.At(backno)
					ExpandMacro(&buffer, reader, line)
					isReplaced = true
				} else {
					buffer.WriteRune(mark)
					buffer.WriteString("-0")
				}
				continue
			} else {
				reader.UnreadRune() // next char of '-'
			}
		}
		if ch == '?' { // !?str?
			var seekStrBuf bytes.Buffer
			lastCharIsQuestionMark := false
			for reader.Len() > 0 {
				ch, _, _ := reader.ReadRune()
				if ch == '?' {
					lastCharIsQuestionMark = true
					break
				}
				seekStrBuf.WriteRune(ch)
			}
			seekStr := seekStrBuf.String()
			found := false
			for i := history_count - 1; i >= 0; i-- {
				his1 := hisObj.At(i)
				if strings.Contains(his1, seekStr) {
					buffer.WriteString(his1)
					isReplaced = true
					found = true
					break
				}
			}
			if !found {
				buffer.WriteRune('?')
				buffer.WriteString(seekStr)
				if lastCharIsQuestionMark {
					buffer.WriteRune('?')
				}
			}
			continue
		}
		// !str
		var seekStrBuf bytes.Buffer
		seekStrBuf.WriteRune(ch)
		for reader.Len() > 0 {
			ch, _, _ := reader.ReadRune()
			if ch == ' ' {
				reader.UnreadRune()
				break
			}
			seekStrBuf.WriteRune(ch)
		}
		seekStr := seekStrBuf.String()
		found := false
		for i := history_count - 1; i >= 0; i-- {
			his1 := hisObj.At(i)
			if strings.HasPrefix(his1, seekStr) {
				buffer.WriteString(his1)
				isReplaced = true
				found = true
				break
			}
		}
		if !found {
			buffer.WriteRune(mark)
			buffer.WriteRune(ch)
		}
	}
	return buffer.String(), isReplaced
}

func ExpandMacro(buffer *bytes.Buffer, reader *strings.Reader, line string) {
	ch, siz, _ := reader.ReadRune()
	if siz > 0 && ch == '^' {
		if words := text.SplitQ(line); len(words) >= 2 {
			buffer.WriteString(words[1])
		}
	} else if siz > 0 && ch == '$' {
		if words := text.SplitQ(line); len(words) >= 2 {
			buffer.WriteString(words[len(words)-1])
		}
	} else if siz > 0 && ch == '*' {
		if words := text.SplitQ(line); len(words) >= 2 {
			buffer.WriteString(strings.Join(words[1:], " "))
		}
	} else if siz > 0 && ch == ':' {
		var n int
		if _, err := fmt.Fscan(reader, &n); err != nil {
			buffer.WriteRune(':')
		} else if words := text.SplitQ(line); n < len(words) {
			buffer.WriteString(words[n])
		}
	} else {
		if siz > 0 {
			reader.UnreadRune()
		}
		buffer.WriteString(line)
	}
}

func CmdHistory(ctx context.Context, cmd *exec.Cmd) (int, error) {
	if ctx == nil {
		fmt.Fprintln(cmd.Stderr, "history not found (case1)")
		return 1, nil
	}
	var num int
	if len(cmd.Args) >= 2 {
		num64, err := strconv.ParseInt(cmd.Args[1], 0, 32)
		if err != nil {
			switch err.(type) {
			case *strconv.NumError:
				return 0, fmt.Errorf(
					"history: %s not a number", cmd.Args[1])
			default:
				return 0, err
			}
		}
		num = int(num64)
		if num < 0 {
			num = -num
		}
	} else {
		num = 10
	}
	start := 0

	historyObj_ := ctx.Value("history")
	if historyObj, ok := historyObj_.(*Container); ok {
		if f, ok := cmd.Stdout.(*os.File); (!ok || isatty.IsTerminal(f.Fd())) &&
			historyObj.Len() > num {

			start = historyObj.Len() - num
		}
		home := os.Getenv("USERPROFILE")
		for i := start; i < historyObj.Len(); i++ {
			row := historyObj.rows[i]
			dir := row.Dir
			if strings.HasPrefix(strings.ToUpper(dir), strings.ToUpper(home)) {
				dir = "~" + dir[len(home):]
			}
			dir = filepath.ToSlash(dir)
			fmt.Fprintf(cmd.Stdout, "%s [%d] %-s (%s)\n",
				row.Stamp.Format("Jan _2 15:04:05"),
				row.Pid,
				row.Text,
				dir)
		}
	} else {
		fmt.Fprintln(cmd.Stderr, "history not found (case 2)")
	}
	return 0, nil
}

const max_histories = 2000

func (hisObj *Container) SaveViaWriter(w io.Writer) {
	i := 0
	if len(hisObj.rows) > max_histories {
		i = len(hisObj.rows) - max_histories
	}
	bw := bufio.NewWriter(w)
	for ; i < len(hisObj.rows); i++ {
		fmt.Fprintln(bw, hisObj.rows[i].String())
	}
	bw.Flush()
}

func (hisObj *Container) Save(path string) error {
	fd, err := os.Create(path)
	if err != nil {
		return err
	}
	hisObj.SaveViaWriter(fd)
	fd.Close()
	return nil
}

func (hisObj *Container) LoadViaReader(reader io.Reader) {
	sc := bufio.NewScanner(reader)
	list := make([][]string, 0, 2000)
	hash := make(map[string]int)
	for sc.Scan() {
		line := sc.Text()
		if lnum, ok := hash[line]; ok {
			// delete duplicated record (marking)
			list[lnum] = nil
		}
		hash[line] = len(list)

		p := strings.Split(line, "\t")
		list = append(list, p)
	}
	for _, p := range list {
		// push only not duplicated record.
		if p != nil {
			var stamp time.Time
			var dir string
			pid := 0
			if len(p) >= 3 {
				dir = p[1]
				stamp, _ = time.Parse("2006-01-02 15:04:05", p[2])
				if len(p) >= 4 {
					pid, _ = strconv.Atoi(p[3])
				}
			}
			hisObj.PushLine(Line{
				Text:  p[0],
				Dir:   dir,
				Stamp: stamp,
				Pid:   pid})
		}
	}
}

func (hisObj *Container) Load(path string) error {
	fd, err := os.Open(path)
	if err != nil {
		return err
	}
	hisObj.LoadViaReader(fd)
	fd.Close()
	return nil
}
<commit_msg>Fix: `history` did not display ID to use !-mark<commit_after>package history

import (
	"bufio"
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/mattn/go-isatty"

	"../text"
)

var Mark = "!"

var DisableMarks = "\"'"

func (hisObj *Container) Replace(line string) (string, bool) {
	var mark rune
	for _, c := range Mark {
		mark = c
		break
	}

	var buffer bytes.Buffer
	isReplaced := false
	reader := strings.NewReader(line)
	history_count := hisObj.Len()

	quotedChar := '\000'

	for reader.Len() > 0 {
		ch, _, _ := reader.ReadRune()
		if quotedChar == '\000' && strings.IndexRune(DisableMarks, ch) >= 0 {
			quotedChar = ch
			buffer.WriteRune(ch)
			continue
		} else if ch == quotedChar {
			quotedChar = '\000'
			buffer.WriteRune(ch)
			continue
		}
		if ch != mark || reader.Len() <= 0 || quotedChar != '\000' {
			buffer.WriteRune(ch)
			continue
		}
		ch, _, _ = reader.ReadRune()
		if n := strings.IndexRune("^$:*", ch); n >= 0 {
			reader.UnreadRune()
			if history_count >= 1 {
				line := hisObj.At(history_count - 1)
				ExpandMacro(&buffer, reader, line)
				isReplaced = true
			}
			continue
		}
		if ch == mark { // !!
			if history_count >= 1 {
				line := hisObj.At(history_count - 1)
				ExpandMacro(&buffer, reader, line)
				isReplaced = true
				continue
			} else {
				buffer.WriteRune(mark)
				continue
			}
		}
		if strings.IndexRune("0123456789", ch) >= 0 { // !n
			reader.UnreadRune()
			var backno int
			fmt.Fscan(reader, &backno)
			backno = backno % history_count
			if 0 <= backno && backno < history_count {
				line := hisObj.At(backno)
				ExpandMacro(&buffer, reader, line)
				isReplaced = true
			}
			continue
		}
		if ch == '-' && reader.Len() > 0 { // !-n
			var number int
			if _, err := fmt.Fscan(reader, &number); err == nil {
				backno := history_count - number
				for backno < 0 {
					backno += history_count
				}
				if 0 <= backno && backno < history_count {
					line := hisObj.At(backno)
					ExpandMacro(&buffer, reader, line)
					isReplaced = true
				} else {
					buffer.WriteRune(mark)
					buffer.WriteString("-0")
				}
				continue
			} else {
				reader.UnreadRune() // next char of '-'
			}
		}
		if ch == '?' { // !?str?
			var seekStrBuf bytes.Buffer
			lastCharIsQuestionMark := false
			for reader.Len() > 0 {
				ch, _, _ := reader.ReadRune()
				if ch == '?' {
					lastCharIsQuestionMark = true
					break
				}
				seekStrBuf.WriteRune(ch)
			}
			seekStr := seekStrBuf.String()
			found := false
			for i := history_count - 1; i >= 0; i-- {
				his1 := hisObj.At(i)
				if strings.Contains(his1, seekStr) {
					buffer.WriteString(his1)
					isReplaced = true
					found = true
					break
				}
			}
			if !found {
				buffer.WriteRune('?')
				buffer.WriteString(seekStr)
				if lastCharIsQuestionMark {
					buffer.WriteRune('?')
				}
			}
			continue
		}
		// !str
		var seekStrBuf bytes.Buffer
		seekStrBuf.WriteRune(ch)
		for reader.Len() > 0 {
			ch, _, _ := reader.ReadRune()
			if ch == ' ' {
				reader.UnreadRune()
				break
			}
			seekStrBuf.WriteRune(ch)
		}
		seekStr := seekStrBuf.String()
		found := false
		for i := history_count - 1; i >= 0; i-- {
			his1 := hisObj.At(i)
			if strings.HasPrefix(his1, seekStr) {
				buffer.WriteString(his1)
				isReplaced = true
				found = true
				break
			}
		}
		if !found {
			buffer.WriteRune(mark)
			buffer.WriteRune(ch)
		}
	}
	return buffer.String(), isReplaced
}

func ExpandMacro(buffer *bytes.Buffer, reader *strings.Reader, line string) {
	ch, siz, _ := reader.ReadRune()
	if siz > 0 && ch == '^' {
		if words := text.SplitQ(line); len(words) >= 2 {
			buffer.WriteString(words[1])
		}
	} else if siz > 0 && ch == '$' {
		if words := text.SplitQ(line); len(words) >= 2 {
			buffer.WriteString(words[len(words)-1])
		}
	} else if siz > 0 && ch == '*' {
		if words := text.SplitQ(line); len(words) >= 2 {
			buffer.WriteString(strings.Join(words[1:], " "))
		}
	} else if siz > 0 && ch == ':' {
		var n int
		if _, err := fmt.Fscan(reader, &n); err != nil {
			buffer.WriteRune(':')
		} else if words := text.SplitQ(line); n < len(words) {
			buffer.WriteString(words[n])
		}
	} else {
		if siz > 0 {
			reader.UnreadRune()
		}
		buffer.WriteString(line)
	}
}

func CmdHistory(ctx context.Context, cmd *exec.Cmd) (int, error) {
	if ctx == nil {
		fmt.Fprintln(cmd.Stderr, "history not found (case1)")
		return 1, nil
	}
	var num int
	if len(cmd.Args) >= 2 {
		num64, err := strconv.ParseInt(cmd.Args[1], 0, 32)
		if err != nil {
			switch err.(type) {
			case *strconv.NumError:
				return 0, fmt.Errorf(
					"history: %s not a number", cmd.Args[1])
			default:
				return 0, err
			}
		}
		num = int(num64)
		if num < 0 {
			num = -num
		}
	} else {
		num = 10
	}
	start := 0

	historyObj_ := ctx.Value("history")
	if historyObj, ok := historyObj_.(*Container); ok {
		if f, ok := cmd.Stdout.(*os.File); (!ok || isatty.IsTerminal(f.Fd())) &&
			historyObj.Len() > num {

			start = historyObj.Len() - num
		}
		home := os.Getenv("USERPROFILE")
		for i := start; i < historyObj.Len(); i++ {
			row := historyObj.rows[i]
			dir := row.Dir
			if strings.HasPrefix(strings.ToUpper(dir), strings.ToUpper(home)) {
				dir = "~" + dir[len(home):]
			}
			dir = filepath.ToSlash(dir)
			fmt.Fprintf(cmd.Stdout, "%4d  %s [%d] %-s (%s)\n",
				i,
				row.Stamp.Format("Jan _2 15:04:05"),
				row.Pid,
				row.Text,
				dir)
		}
	} else {
		fmt.Fprintln(cmd.Stderr, "history not found (case 2)")
	}
	return 0, nil
}

const max_histories = 2000

func (hisObj *Container) SaveViaWriter(w io.Writer) {
	i := 0
	if len(hisObj.rows) > max_histories {
		i = len(hisObj.rows) - max_histories
	}
	bw := bufio.NewWriter(w)
	for ; i < len(hisObj.rows); i++ {
		fmt.Fprintln(bw, hisObj.rows[i].String())
	}
	bw.Flush()
}

func (hisObj *Container) Save(path string) error {
	fd, err := os.Create(path)
	if err != nil {
		return err
	}
	hisObj.SaveViaWriter(fd)
	fd.Close()
	return nil
}

func (hisObj *Container) LoadViaReader(reader io.Reader) {
	sc := bufio.NewScanner(reader)
	list := make([][]string, 0, 2000)
	hash := make(map[string]int)
	for sc.Scan() {
		line := sc.Text()
		if lnum, ok := hash[line]; ok {
			// delete duplicated record (marking)
			list[lnum] = nil
		}
		hash[line] = len(list)

		p := strings.Split(line, "\t")
		list = append(list, p)
	}
	for _, p := range list {
		// push only not duplicated record.
		if p != nil {
			var stamp time.Time
			var dir string
			pid := 0
			if len(p) >= 3 {
				dir = p[1]
				stamp, _ = time.Parse("2006-01-02 15:04:05", p[2])
				if len(p) >= 4 {
					pid, _ = strconv.Atoi(p[3])
				}
			}
			hisObj.PushLine(Line{
				Text:  p[0],
				Dir:   dir,
				Stamp: stamp,
				Pid:   pid})
		}
	}
}

func (hisObj *Container) Load(path string) error {
	fd, err := os.Open(path)
	if err != nil {
		return err
	}
	hisObj.LoadViaReader(fd)
	fd.Close()
	return nil
}
<|endoftext|>


<commit_before>package goat

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"net"
	"strconv"
	"strings"
)

// UdpConnHandler handles incoming UDP network connections
type UdpConnHandler struct {
}

// Handle incoming UDP connections and return response
func (u UdpConnHandler) Handle(l *net.UDPConn, udpDoneChan chan bool) {
	// Create shutdown function
	go func(l *net.UDPConn, udpDoneChan chan bool) {
		// Wait for done signal
		<-Static.ShutdownChan

		// Close listener
		l.Close()
		udpDoneChan <- true
	}(l, udpDoneChan)

	// Initial connection handshake
	initId := 4715956011469373440

	for {
		buf := make([]byte, 2048)
		rlen, addr, _ := l.ReadFromUDP(buf)

		// Verify length is at least 16 bytes
		if rlen < 16 {
			Static.LogChan <- "Invalid length"
			continue
		}

		//connId := binary.BigEndian.Uint64(buf[0:8])
		action := binary.BigEndian.Uint32(buf[8:12])
		transId := binary.BigEndian.Uint32(buf[12:16])

		// Verify valid connection ID
		_ = initId
		/*
			if connId != initId {
				Static.LogChan <- "Invalid connection ID"
				continue
			}
		*/

		// Action switch
		switch action {
		// Connect
		case 0:
			res := bytes.NewBuffer(make([]byte, 0))

			// Action
			binary.Write(res, binary.BigEndian, uint32(0))
			// Transaction ID
			binary.Write(res, binary.BigEndian, uint32(transId))
			// Connection ID
			binary.Write(res, binary.BigEndian, uint64(1234))

			_, err := l.WriteToUDP(res.Bytes(), addr)
			if err != nil {
				Static.LogChan <- err.Error()
				continue
			}

			continue
		// Announce
		case 1:
			query := map[string]string{}

			// Mark client as UDP
			query["udp"] = "1"

			// Connection ID
			connId := binary.BigEndian.Uint64(buf[0:8])

			// Action
			action := binary.BigEndian.Uint32(buf[8:12])

			// Transaction ID
			transId := binary.BigEndian.Uint32(buf[12:16])
			transIdBuf := buf[12:16]

			// Info hash
			query["info_hash"] = string(buf[16:36])

			// Peer ID
			query["peer_id"] = string(buf[36:56])

			// Downloaded
			t, _ := strconv.ParseInt(hex.EncodeToString(buf[56:64]), 16, 64)
			query["downloaded"] = strconv.FormatInt(t, 10)

			// Left
			t, _ = strconv.ParseInt(hex.EncodeToString(buf[64:72]), 16, 64)
			query["left"] = strconv.FormatInt(t, 10)

			// Uploaded
			t, _ = strconv.ParseInt(hex.EncodeToString(buf[72:80]), 16, 64)
			query["uploaded"] = strconv.FormatInt(t, 10)

			// Event
			t, _ = strconv.ParseInt(hex.EncodeToString(buf[80:84]), 16, 32)
			query["event"] = strconv.FormatInt(t, 10)

			// Convert event to actual string
			switch query["event"] {
			case "0":
				query["event"] = ""
			case "1":
				query["event"] = "completed"
			case "2":
				query["event"] = "started"
			case "3":
				query["event"] = "stopped"
			}

			// IP address
			t, _ = strconv.ParseInt(hex.EncodeToString(buf[84:88]), 16, 32)
			query["ip"] = strconv.FormatInt(t, 10)

			// If no IP address set, use the UDP source
			if query["ip"] == "0" {
				query["ip"] = strings.Split(addr.String(), ":")[0]
			}

			// Key
			query["key"] = hex.EncodeToString(buf[88:92])

			// Numwant
			query["numwant"] = hex.EncodeToString(buf[92:96])

			// If numwant is hex max value, default to 50
			if query["numwant"] == "ffffffff" {
				query["numwant"] = "50"
			}

			// Port
			t, _ = strconv.ParseInt(hex.EncodeToString(buf[96:98]), 16, 32)
			query["port"] = strconv.FormatInt(t, 10)

			_, _, _ = connId, transId, action

			// Trigger an announce
			resChan := make(chan []byte)
			go TrackerAnnounce(UserRecord{}, query, transIdBuf, resChan)

			_, err := l.WriteToUDP(<-resChan, addr)
			if err != nil {
				Static.LogChan <- err.Error()
				continue
			}
		default:
			Static.LogChan <- "Invalid action"
			continue
		}
	}
}
<commit_msg>UDP cleanup and optimization<commit_after>package goat

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"net"
	"strconv"
	"strings"
)

// Handshake for UDP tracker protocol
const INIT_ID = 4497486125440

// UdpConnHandler handles incoming UDP network connections
type UdpConnHandler struct {
}

// Handle incoming UDP connections and return response
func (u UdpConnHandler) Handle(l *net.UDPConn, udpDoneChan chan bool) {
	// Create shutdown function
	go func(l *net.UDPConn, udpDoneChan chan bool) {
		// Wait for done signal
		<-Static.ShutdownChan

		// Close listener
		l.Close()
		udpDoneChan <- true
	}(l, udpDoneChan)

	first := true
	for {
		buf := make([]byte, 2048)
		rlen, addr, err := l.ReadFromUDP(buf)
		if err != nil {
			Static.LogChan <- err.Error()
			continue
		}

		// Verify length is at least 16 bytes
		if rlen < 16 {
			Static.LogChan <- "Invalid length"
			continue
		}

		// Current connection ID (initially handshake, then generated by tracker)
		connId := binary.BigEndian.Uint64(buf[0:8])
		// Action integer (connect: 0, announce: 1)
		action := binary.BigEndian.Uint32(buf[8:12])
		// Transaction ID, to match between requests
		transId := buf[12:16]

		// On first run, verify valid connection ID
		if first {
			if connId != INIT_ID {
				Static.LogChan <- "Invalid connection handshake"
				l.WriteToUDP(UdpTrackerError("Invalid connection handshake", transId), addr)
				continue
			}
			first = false
		}

		// Action switch
		switch action {
		// Connect
		case 0:
			res := bytes.NewBuffer(make([]byte, 0))

			// Action
			binary.Write(res, binary.BigEndian, uint32(0))
			// Transaction ID
			binary.Write(res, binary.BigEndian, transId)
			// Connection ID, generated for this session
			binary.Write(res, binary.BigEndian, uint64(RandRange(0, 1000000000)))

			_, err := l.WriteToUDP(res.Bytes(), addr)
			if err != nil {
				Static.LogChan <- err.Error()
				continue
			}

			continue
		// Announce
		case 1:
			query := map[string]string{}

			// Ignoring these for now, because clients function sanely without them
			// Connection ID: buf[0:8]
			// Action: buf[8:12]

			// Mark client as UDP
			query["udp"] = "1"

			// Transaction ID
			transId := buf[12:16]

			// Info hash
			query["info_hash"] = string(buf[16:36])

			// Skipped: peer_id: buf[36:56]

			// Downloaded
			t, _ := strconv.ParseInt(hex.EncodeToString(buf[56:64]), 16, 64)
			query["downloaded"] = strconv.FormatInt(t, 10)

			// Left
			t, _ = strconv.ParseInt(hex.EncodeToString(buf[64:72]), 16, 64)
			query["left"] = strconv.FormatInt(t, 10)

			// Uploaded
			t, _ = strconv.ParseInt(hex.EncodeToString(buf[72:80]), 16, 64)
			query["uploaded"] = strconv.FormatInt(t, 10)

			// Event
			t, _ = strconv.ParseInt(hex.EncodeToString(buf[80:84]), 16, 32)
			query["event"] = strconv.FormatInt(t, 10)

			// Convert event to actual string
			switch query["event"] {
			case "0":
				query["event"] = ""
			case "1":
				query["event"] = "completed"
			case "2":
				query["event"] = "started"
			case "3":
				query["event"] = "stopped"
			}

			// IP address
			t, _ = strconv.ParseInt(hex.EncodeToString(buf[84:88]), 16, 32)
			query["ip"] = strconv.FormatInt(t, 10)

			// If no IP address set, use the UDP source
			if query["ip"] == "0" {
				query["ip"] = strings.Split(addr.String(), ":")[0]
			}

			// Key
			query["key"] = hex.EncodeToString(buf[88:92])

			// Numwant
			query["numwant"] = hex.EncodeToString(buf[92:96])

			// If numwant is hex max value, default to 50
			if query["numwant"] == "ffffffff" {
				query["numwant"] = "50"
			}

			// Port
			t, _ = strconv.ParseInt(hex.EncodeToString(buf[96:98]), 16, 32)
			query["port"] = strconv.FormatInt(t, 10)

			// Trigger an anonymous announce
			resChan := make(chan []byte)
			go TrackerAnnounce(UserRecord{}, query, transId, resChan)

			_, err := l.WriteToUDP(<-resChan, addr)
			if err != nil {
				Static.LogChan <- err.Error()
				continue
			}
		default:
			Static.LogChan <- "Invalid action"
			continue
		}
	}
}
<|endoftext|>


<commit_before>package generators

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"

	"github.com/juju/errgo"
	"github.com/yext/edward/services"
)

func init() {
	RegisterGenerator(&GoGenerator{})
}

type GoGenerator struct {
	basePath string
	found    map[string]string
}

func (v *GoGenerator) Name() string {
	return "go"
}

func (v *GoGenerator) StartWalk(path string) {
	v.basePath = path
	v.found = make(map[string]string)
}

func (v *GoGenerator) StopWalk() {
}

func (v *GoGenerator) VisitDir(path string, f os.FileInfo, err error) error {
	if err != nil {
		return errgo.Mask(err)
	}

	if _, err := os.Stat(path); err != nil {
		return errgo.Mask(err)
	}

	files, _ := ioutil.ReadDir(path)
	for _, f := range files {
		fPath := filepath.Join(path, f.Name())
		if filepath.Ext(fPath) != ".go" {
			continue
		}

		input, err := ioutil.ReadFile(fPath)
		if err != nil {
			return errgo.Mask(err)
		}

		packageExpr := regexp.MustCompile(`package main\n`)
		if packageExpr.Match(input) {
			packageName := filepath.Base(path)
			packagePath, err := filepath.Rel(v.basePath, path)
			if err != nil {
				return errgo.Mask(err)
			}
			v.found[packageName] = packagePath
		}

	}

	return nil
}

func (v *GoGenerator) Found() []*services.ServiceConfig {
	var outServices []*services.ServiceConfig

	for packageName, packagePath := range v.found {
		outServices = append(outServices, goService(packageName, packagePath))
	}

	return outServices
}

func goService(name, packagePath string) *services.ServiceConfig {
	service := &services.ServiceConfig{
		Name: name,
		Path: &packagePath,
		Env:  []string{},
		Commands: services.ServiceConfigCommands{
			Build:  "go install",
			Launch: name,
		},
	}

	service.SetWatch(services.ServiceWatch{
		Service:       service,
		IncludedPaths: []string{packagePath},
	})

	return service
}
<commit_msg>Pull a list of all imports and include all the ones that exist in go watch lists.<commit_after>package generators

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/juju/errgo"
	"github.com/yext/edward/services"
)

func init() {
	RegisterGenerator(&GoGenerator{})
}

type GoGenerator struct {
	basePath string
	found    map[string]string
}

func (v *GoGenerator) Name() string {
	return "go"
}

func (v *GoGenerator) StartWalk(path string) {
	v.basePath = path
	v.found = make(map[string]string)
}

func (v *GoGenerator) StopWalk() {
}

func (v *GoGenerator) VisitDir(path string, f os.FileInfo, err error) error {
	if err != nil {
		return errgo.Mask(err)
	}

	if _, err := os.Stat(path); err != nil {
		return errgo.Mask(err)
	}

	files, _ := ioutil.ReadDir(path)
	for _, f := range files {
		fPath := filepath.Join(path, f.Name())
		if filepath.Ext(fPath) != ".go" {
			continue
		}

		input, err := ioutil.ReadFile(fPath)
		if err != nil {
			return errgo.Mask(err)
		}

		packageExpr := regexp.MustCompile(`package main\n`)
		if packageExpr.Match(input) {
			packageName := filepath.Base(path)
			packagePath, err := filepath.Rel(v.basePath, path)
			if err != nil {
				return errgo.Mask(err)
			}
			v.found[packageName] = packagePath
		}

	}

	return nil
}

func (v *GoGenerator) Found() []*services.ServiceConfig {
	var outServices []*services.ServiceConfig

	for packageName, packagePath := range v.found {
		service, err := v.goService(packageName, packagePath)
		if err == nil {
			outServices = append(outServices, service)
		}
		// TODO: Log any error?
	}

	return outServices
}

func (v *GoGenerator) goService(name, packagePath string) (*services.ServiceConfig, error) {
	service := &services.ServiceConfig{
		Name: name,
		Path: &packagePath,
		Env:  []string{},
		Commands: services.ServiceConfigCommands{
			Build:  "go install",
			Launch: name,
		},
	}

	watch, err := v.createWatch(service)
	if err != nil {
		return nil, errgo.Mask(err)
	}
	service.SetWatch(watch)

	return service, nil
}

func (v *GoGenerator) createWatch(service *services.ServiceConfig) (services.ServiceWatch, error) {
	return services.ServiceWatch{
		Service:       service,
		IncludedPaths: v.getImportList(service),
	}, nil
}

func (v *GoGenerator) getImportList(service *services.ServiceConfig) []string {
	if service.Path == nil {
		return nil
	}

	var imports = []string{}
	cmd := exec.Command("go", "list", "-f", "{{ join .Imports \":\" }}")
	cmd.Dir = *service.Path
	var out bytes.Buffer
	var errBuf bytes.Buffer
	cmd.Stderr = &errBuf
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		fmt.Println(errBuf.String())
		return []string{*service.Path}
	}
	imports = append(imports, strings.Split(out.String(), ":")...)

	var checkedImports = []string{*service.Path}
	for _, i := range imports {
		path := os.ExpandEnv(fmt.Sprintf("$GOPATH/src/%v", i))
		if _, err := os.Stat(path); err == nil {
			rel, err := filepath.Rel(v.basePath, path)
			if err != nil {
				// TODO: Handle this error more effectively
				fmt.Println(err)
				continue
			}
			checkedImports = append(checkedImports, rel)
		}
	}
	return checkedImports
}
<|endoftext|>


<commit_before>package network

import (
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"testing"
)

func TestFastModularNetworkSolver_RecursiveSteps(t *testing.T) {
	net := buildNetwork()

	// Create network solver
	data := []float64{0.5, 1.1} // BIAS is 1.0 by definition
	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	err = fmm.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	// Activate objective network
	//
	data = append(data, 1.0) // BIAS is a third object
	err = net.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	depth, err := net.MaxActivationDepth()
	require.NoError(t, err, "failed to calculate max depth")

	t.Logf("depth: %d\n", depth)
	logNetworkActivationPath(net, t)

	res, err := net.ForwardSteps(depth)
	require.NoError(t, err, "error when trying to activate objective network")
	require.True(t, res, "failed to activate objective network")

	// Do recursive activation of the Fast Network Solver
	//
	res, err = fmm.RecursiveSteps()
	require.NoError(t, err, "error when trying to activate Fast Network Solver")
	require.True(t, res, "recursive activation failed")

	// Compare activations of objective network and Fast Network Solver
	//
	fmmOutputs := fmm.ReadOutputs()
	require.Equal(t, len(net.Outputs), len(fmmOutputs))

	for i, out := range fmmOutputs {
		assert.Equal(t, net.Outputs[i].Activation, out, "wrong activation at: %d", i)
	}
}

func TestFastModularNetworkSolver_ForwardSteps(t *testing.T) {
	net := buildModularNetwork()

	// create network solver
	data := []float64{1.0, 2.0} // bias inherent
	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	err = fmm.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	depth, err := net.MaxActivationDepth()
	require.NoError(t, err, "failed to calculate max depth")

	t.Logf("depth: %d\n", depth)
	logNetworkActivationPath(net, t)

	// activate objective network
	//
	data = append(data, 1.0) // BIAS is third object
	err = net.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")
	res, err := net.ForwardSteps(depth)
	require.NoError(t, err, "error when trying to activate objective network")
	require.True(t, res, "failed to activate objective network")

	// do forward steps through the solver and test results
	//
	res, err = fmm.ForwardSteps(depth)
	require.NoError(t, err, "error while do forward steps")
	require.True(t, res, "forward steps returned false")

	// check results by comparing activations of objective network and fast network solver
	//
	outputs := fmm.ReadOutputs()
	for i, out := range outputs {
		assert.Equal(t, net.Outputs[i].Activation, out, "wrong activation at: %d", i)
	}
}

func TestFastModularNetworkSolver_Relax(t *testing.T) {
	net := buildModularNetwork()

	// create network solver
	data := []float64{1.5, 2.0} // bias inherent
	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	err = fmm.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	depth, err := net.MaxActivationDepth()
	require.NoError(t, err, "failed to calculate max depth")

	t.Logf("depth: %d\n", depth)
	logNetworkActivationPath(net, t)

	// activate objective network
	//
	data = append(data, 1.0) // BIAS is third object
	err = net.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")
	res, err := net.ForwardSteps(depth)
	require.NoError(t, err, "error when trying to activate objective network")
	require.True(t, res, "failed to activate objective network")

	// do relaxation of fast network solver
	//
	res, err = fmm.Relax(depth, 1)
	require.NoError(t, err)
	require.True(t, res, "failed to relax within given maximal steps number")

	// check results by comparing activations of objective network and fast network solver
	//
	outputs := fmm.ReadOutputs()
	for i, out := range outputs {
		assert.Equal(t, net.Outputs[i].Activation, out, "wrong activation at: %d", i)
	}
}

func TestFastModularNetworkSolver_Flush(t *testing.T) {
	net := buildModularNetwork()

	// create network solver
	data := []float64{1.5, 2.0} // bias inherent
	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	err = fmm.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	fmmImpl := fmm.(*FastModularNetworkSolver)
	// test that network has active signals
	active := countActiveSignals(fmmImpl)
	assert.NotZero(t, active, "no active signal found")

	// flush and test
	res, err := fmm.Flush()
	require.NoError(t, err)
	require.True(t, res, "failed to flush network")

	active = countActiveSignals(fmmImpl)
	assert.Zero(t, active, "after flush the active signal still present")
}

func TestFastModularNetworkSolver_NodeCount(t *testing.T) {
	net := buildModularNetwork()

	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	assert.Equal(t, 9, fmm.NodeCount())
}

func TestFastModularNetworkSolver_LinkCount(t *testing.T) {
	net := buildModularNetwork()

	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	assert.Equal(t, 9, fmm.LinkCount())
}

func countActiveSignals(impl *FastModularNetworkSolver) int {
	active := 0
	for i := impl.biasNeuronCount; i < impl.totalNeuronCount; i++ {
		if impl.neuronSignals[i] != 0.0 {
			active++
		}
	}
	return active
}
<commit_msg>Added test case TestFastModularNetworkSolver_LoadSensors<commit_after>package network

import (
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"testing"
)

func TestFastModularNetworkSolver_LoadSensors(t *testing.T) {
	net := buildNetwork()

	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")

	// test normal
	data := []float64{0.5, 1.1}
	err = fmm.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	// test abnormal
	data = append(data, 1.0)
	err = fmm.LoadSensors(data)
	require.EqualError(t, err, ErrNetUnsupportedSensorsArraySize.Error())
}

func TestFastModularNetworkSolver_RecursiveSteps(t *testing.T) {
	net := buildNetwork()

	// Create network solver
	data := []float64{0.5, 1.1} // BIAS is 1.0 by definition
	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	err = fmm.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	// Activate objective network
	//
	data = append(data, 1.0) // BIAS is a third object
	err = net.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	depth, err := net.MaxActivationDepth()
	require.NoError(t, err, "failed to calculate max depth")

	t.Logf("depth: %d\n", depth)
	logNetworkActivationPath(net, t)

	res, err := net.ForwardSteps(depth)
	require.NoError(t, err, "error when trying to activate objective network")
	require.True(t, res, "failed to activate objective network")

	// Do recursive activation of the Fast Network Solver
	//
	res, err = fmm.RecursiveSteps()
	require.NoError(t, err, "error when trying to activate Fast Network Solver")
	require.True(t, res, "recursive activation failed")

	// Compare activations of objective network and Fast Network Solver
	//
	fmmOutputs := fmm.ReadOutputs()
	require.Equal(t, len(net.Outputs), len(fmmOutputs))

	for i, out := range fmmOutputs {
		assert.Equal(t, net.Outputs[i].Activation, out, "wrong activation at: %d", i)
	}
}

func TestFastModularNetworkSolver_ForwardSteps(t *testing.T) {
	net := buildModularNetwork()

	// create network solver
	data := []float64{1.0, 2.0} // bias inherent
	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	err = fmm.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	depth, err := net.MaxActivationDepth()
	require.NoError(t, err, "failed to calculate max depth")

	t.Logf("depth: %d\n", depth)
	logNetworkActivationPath(net, t)

	// activate objective network
	//
	data = append(data, 1.0) // BIAS is third object
	err = net.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")
	res, err := net.ForwardSteps(depth)
	require.NoError(t, err, "error when trying to activate objective network")
	require.True(t, res, "failed to activate objective network")

	// do forward steps through the solver and test results
	//
	res, err = fmm.ForwardSteps(depth)
	require.NoError(t, err, "error while do forward steps")
	require.True(t, res, "forward steps returned false")

	// check results by comparing activations of objective network and fast network solver
	//
	outputs := fmm.ReadOutputs()
	for i, out := range outputs {
		assert.Equal(t, net.Outputs[i].Activation, out, "wrong activation at: %d", i)
	}
}

func TestFastModularNetworkSolver_Relax(t *testing.T) {
	net := buildModularNetwork()

	// create network solver
	data := []float64{1.5, 2.0} // bias inherent
	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	err = fmm.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	depth, err := net.MaxActivationDepth()
	require.NoError(t, err, "failed to calculate max depth")

	t.Logf("depth: %d\n", depth)
	logNetworkActivationPath(net, t)

	// activate objective network
	//
	data = append(data, 1.0) // BIAS is third object
	err = net.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")
	res, err := net.ForwardSteps(depth)
	require.NoError(t, err, "error when trying to activate objective network")
	require.True(t, res, "failed to activate objective network")

	// do relaxation of fast network solver
	//
	res, err = fmm.Relax(depth, 1)
	require.NoError(t, err)
	require.True(t, res, "failed to relax within given maximal steps number")

	// check results by comparing activations of objective network and fast network solver
	//
	outputs := fmm.ReadOutputs()
	for i, out := range outputs {
		assert.Equal(t, net.Outputs[i].Activation, out, "wrong activation at: %d", i)
	}
}

func TestFastModularNetworkSolver_Flush(t *testing.T) {
	net := buildModularNetwork()

	// create network solver
	data := []float64{1.5, 2.0} // bias inherent
	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	err = fmm.LoadSensors(data)
	require.NoError(t, err, "failed to load sensors")

	fmmImpl := fmm.(*FastModularNetworkSolver)
	// test that network has active signals
	active := countActiveSignals(fmmImpl)
	assert.NotZero(t, active, "no active signal found")

	// flush and test
	res, err := fmm.Flush()
	require.NoError(t, err)
	require.True(t, res, "failed to flush network")

	active = countActiveSignals(fmmImpl)
	assert.Zero(t, active, "after flush the active signal still present")
}

func TestFastModularNetworkSolver_NodeCount(t *testing.T) {
	net := buildModularNetwork()

	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	assert.Equal(t, 9, fmm.NodeCount())
}

func TestFastModularNetworkSolver_LinkCount(t *testing.T) {
	net := buildModularNetwork()

	fmm, err := net.FastNetworkSolver()
	require.NoError(t, err, "failed to create fast network solver")
	assert.Equal(t, 9, fmm.LinkCount())
}

func countActiveSignals(impl *FastModularNetworkSolver) int {
	active := 0
	for i := impl.biasNeuronCount; i < impl.totalNeuronCount; i++ {
		if impl.neuronSignals[i] != 0.0 {
			active++
		}
	}
	return active
}
<|endoftext|>


<commit_before>package completion

import "bytes"
import "fmt"
import "os"
import "path"
import "strings"
import "unicode"

import "../box"
import "../conio"

var pathHash []string

func isExecutable(path string) bool {
	path = strings.ToLower(path)
	if strings.HasSuffix(path, ".exe") {
		return true
	}
	if strings.HasSuffix(path, ".cmd") {
		return true
	}
	if strings.HasSuffix(path, ".bat") {
		return true
	}
	if strings.HasSuffix(path, ".com") {
		return true
	}
	return false
}

func listUpFiles(str string) ([]string, error) {
	str = strings.Replace(strings.Replace(str, "\\", "/", -1), "\"", "", -1)
	var directory string
	str = strings.Replace(str, "\\", "/", -1)
	if strings.HasSuffix(str, "/") {
		directory = path.Join(str, ".")
	} else {
		directory = path.Dir(str)
	}
	cutprefix := 0
	if strings.HasPrefix(directory, "/") {
		wd, _ := os.Getwd()
		directory = wd[0:2] + directory
		cutprefix = 2
	}

	fd, fdErr := os.Open(directory)
	if fdErr != nil {
		return nil, fdErr
	}
	defer fd.Close()
	files, filesErr := fd.Readdir(-1)
	if filesErr != nil {
		return nil, filesErr
	}
	commons := make([]string, 0)
	STR := strings.ToUpper(str)
	for _, node1 := range files {
		name := path.Join(directory, node1.Name())
		if node1.IsDir() {
			name += "/"
		}
		if cutprefix > 0 {
			name = name[2:]
		}
		nameUpr := strings.ToUpper(name)
		if strings.HasPrefix(nameUpr, STR) {
			commons = append(commons, name)
		}
	}
	return commons, nil
}

func listUpCommands(str string) ([]string, error) {
	listTmp, listErr := listUpFiles(str)
	if listErr != nil {
		return nil, listErr
	}
	list := make([]string, 0)
	for _, fname := range listTmp {
		if strings.HasSuffix(fname, "/") || strings.HasSuffix(fname, "\\") || isExecutable(fname) {
			list = append(list, fname)
		}
	}
	pathEnv := os.Getenv("PATH")
	dirList := strings.Split(pathEnv, ";")
	strUpr := strings.ToUpper(str)
	for _, dir1 := range dirList {
		dirHandle, dirErr := os.Open(dir1)
		if dirErr != nil {
			continue
		}
		defer dirHandle.Close()
		files, filesErr := dirHandle.Readdir(0)
		if filesErr != nil {
			continue
		}
		for _, file1 := range files {
			name1Upr := strings.ToUpper(file1.Name())
			if !strings.HasPrefix(name1Upr, strUpr) {
				continue
			}
			if file1.IsDir() {
				continue
			}
			name := file1.Name()
			if isExecutable(name) {
				list = append(list, path.Base(name))
			}
		}
	}
	return list, nil
}
func KeyFuncCompletionList(this *conio.ReadLineBuffer) conio.KeyFuncResult {
	str, pos := this.CurrentWord()
	var list []string
	if pos > 0 {
		list, _ = listUpFiles(str)
	} else {
		list, _ = listUpCommands(str)
	}
	if list == nil {
		return conio.CONTINUE
	}
	fmt.Print("\n")
	box.Print(list, 80, os.Stdout)
	this.RepaintAll()
	return conio.CONTINUE
}

func getCommmon(list []string) string {
	common := list[0]
	for _, f := range list[1:] {
		cr := strings.NewReader(common)
		fr := strings.NewReader(f)
		i := 0
		var buffer bytes.Buffer
		for {
			ch, _, cerr := cr.ReadRune()
			fh, _, ferr := fr.ReadRune()
			if cerr != nil || ferr != nil || unicode.ToUpper(ch) != unicode.ToUpper(fh) {
				break
			}
			buffer.WriteRune(ch)
			i++
		}
		common = buffer.String()
	}
	return common
}

func compareWithoutQuote(this string, that string) bool {
	return strings.Replace(this, "\"", "", -1) == strings.Replace(that, "\"", "", -1)
}

func KeyFuncCompletion(this *conio.ReadLineBuffer) conio.KeyFuncResult {
	str, wordStart := this.CurrentWord()

	slashToBackSlash := true
	firstFoundSlashPos := strings.IndexRune(str, '/')
	firstFoundBackSlashPos := strings.IndexRune(str, '\\')
	if firstFoundSlashPos >= 0 && firstFoundBackSlashPos >= 0 && firstFoundSlashPos < firstFoundBackSlashPos {
		slashToBackSlash = false
	}

	var list []string
	var err error
	if wordStart > 0 {
		list, err = listUpFiles(str)
	} else {
		list, err = listUpCommands(str)
	}
	if err != nil || len(list) <= 0 {
		return conio.CONTINUE
	}
	commonStr := getCommmon(list)
	needQuote := strings.ContainsRune(str, '"')
	if !needQuote {
		for _, node := range list {
			if strings.ContainsRune(node, ' ') {
				needQuote = true
				break
			}
		}
	}
	if needQuote {
		var buffer bytes.Buffer
		buffer.WriteRune('"')
		buffer.WriteString(commonStr)
		if len(list) <= 1 {
			buffer.WriteRune('"')
		}
		commonStr = buffer.String()
	}
	if len(list) == 1 && !strings.HasSuffix(commonStr, "/") && !strings.HasSuffix(commonStr, "/\"") {
		commonStr += " "
	}
	if slashToBackSlash {
		commonStr = strings.Replace(commonStr, "/", "\\", -1)
	}
	if compareWithoutQuote(str, commonStr) {
		return KeyFuncCompletionList(this)
	}
	this.ReplaceAndRepaint(wordStart, commonStr)
	return conio.CONTINUE
}
<commit_msg>コマンド名補完で同一名が複数あった時に一つにまとめる処理を追加<commit_after>package completion

import "bytes"
import "fmt"
import "os"
import "path"
import "strings"
import "unicode"

import "../box"
import "../conio"

var pathHash []string

func isExecutable(path string) bool {
	path = strings.ToLower(path)
	if strings.HasSuffix(path, ".exe") {
		return true
	}
	if strings.HasSuffix(path, ".cmd") {
		return true
	}
	if strings.HasSuffix(path, ".bat") {
		return true
	}
	if strings.HasSuffix(path, ".com") {
		return true
	}
	return false
}

func listUpFiles(str string) ([]string, error) {
	str = strings.Replace(strings.Replace(str, "\\", "/", -1), "\"", "", -1)
	var directory string
	str = strings.Replace(str, "\\", "/", -1)
	if strings.HasSuffix(str, "/") {
		directory = path.Join(str, ".")
	} else {
		directory = path.Dir(str)
	}
	cutprefix := 0
	if strings.HasPrefix(directory, "/") {
		wd, _ := os.Getwd()
		directory = wd[0:2] + directory
		cutprefix = 2
	}

	fd, fdErr := os.Open(directory)
	if fdErr != nil {
		return nil, fdErr
	}
	defer fd.Close()
	files, filesErr := fd.Readdir(-1)
	if filesErr != nil {
		return nil, filesErr
	}
	commons := make([]string, 0)
	STR := strings.ToUpper(str)
	for _, node1 := range files {
		name := path.Join(directory, node1.Name())
		if node1.IsDir() {
			name += "/"
		}
		if cutprefix > 0 {
			name = name[2:]
		}
		nameUpr := strings.ToUpper(name)
		if strings.HasPrefix(nameUpr, STR) {
			commons = append(commons, name)
		}
	}
	return commons, nil
}

func listUpCommands(str string) ([]string, error) {
	listTmp, listErr := listUpFiles(str)
	if listErr != nil {
		return nil, listErr
	}
	list := make([]string, 0)
	for _, fname := range listTmp {
		if strings.HasSuffix(fname, "/") || strings.HasSuffix(fname, "\\") || isExecutable(fname) {
			list = append(list, fname)
		}
	}
	pathEnv := os.Getenv("PATH")
	dirList := strings.Split(pathEnv, ";")
	strUpr := strings.ToUpper(str)
	for _, dir1 := range dirList {
		dirHandle, dirErr := os.Open(dir1)
		if dirErr != nil {
			continue
		}
		defer dirHandle.Close()
		files, filesErr := dirHandle.Readdir(0)
		if filesErr != nil {
			continue
		}
		for _, file1 := range files {
			name1Upr := strings.ToUpper(file1.Name())
			if !strings.HasPrefix(name1Upr, strUpr) {
				continue
			}
			if file1.IsDir() {
				continue
			}
			name := file1.Name()
			if isExecutable(name) {
				list = append(list, path.Base(name))
			}
		}
	}
	// remove dupcalites
	uniq := make([]string, 0)
	lastone := ""
	for _, cur := range list {
		if cur != lastone {
			uniq = append(uniq, cur)
		}
		lastone = cur
	}
	return uniq, nil
}
func KeyFuncCompletionList(this *conio.ReadLineBuffer) conio.KeyFuncResult {
	str, pos := this.CurrentWord()
	var list []string
	if pos > 0 {
		list, _ = listUpFiles(str)
	} else {
		list, _ = listUpCommands(str)
	}
	if list == nil {
		return conio.CONTINUE
	}
	fmt.Print("\n")
	box.Print(list, 80, os.Stdout)
	this.RepaintAll()
	return conio.CONTINUE
}

func getCommmon(list []string) string {
	common := list[0]
	for _, f := range list[1:] {
		cr := strings.NewReader(common)
		fr := strings.NewReader(f)
		i := 0
		var buffer bytes.Buffer
		for {
			ch, _, cerr := cr.ReadRune()
			fh, _, ferr := fr.ReadRune()
			if cerr != nil || ferr != nil || unicode.ToUpper(ch) != unicode.ToUpper(fh) {
				break
			}
			buffer.WriteRune(ch)
			i++
		}
		common = buffer.String()
	}
	return common
}

func compareWithoutQuote(this string, that string) bool {
	return strings.Replace(this, "\"", "", -1) == strings.Replace(that, "\"", "", -1)
}

func KeyFuncCompletion(this *conio.ReadLineBuffer) conio.KeyFuncResult {
	str, wordStart := this.CurrentWord()

	slashToBackSlash := true
	firstFoundSlashPos := strings.IndexRune(str, '/')
	firstFoundBackSlashPos := strings.IndexRune(str, '\\')
	if firstFoundSlashPos >= 0 && firstFoundBackSlashPos >= 0 && firstFoundSlashPos < firstFoundBackSlashPos {
		slashToBackSlash = false
	}

	var list []string
	var err error
	if wordStart > 0 {
		list, err = listUpFiles(str)
	} else {
		list, err = listUpCommands(str)
	}
	if err != nil || len(list) <= 0 {
		return conio.CONTINUE
	}
	commonStr := getCommmon(list)
	needQuote := strings.ContainsRune(str, '"')
	if !needQuote {
		for _, node := range list {
			if strings.ContainsRune(node, ' ') {
				needQuote = true
				break
			}
		}
	}
	if needQuote {
		var buffer bytes.Buffer
		buffer.WriteRune('"')
		buffer.WriteString(commonStr)
		if len(list) <= 1 {
			buffer.WriteRune('"')
		}
		commonStr = buffer.String()
	}
	if len(list) == 1 && !strings.HasSuffix(commonStr, "/") && !strings.HasSuffix(commonStr, "/\"") {
		commonStr += " "
	}
	if slashToBackSlash {
		commonStr = strings.Replace(commonStr, "/", "\\", -1)
	}
	if compareWithoutQuote(str, commonStr) {
		return KeyFuncCompletionList(this)
	}
	this.ReplaceAndRepaint(wordStart, commonStr)
	return conio.CONTINUE
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"os"
	"sync"
	"time"

	"github.com/yuuki/diamondb/pkg/model"
	"github.com/yuuki/diamondb/pkg/timeparser"
	"github.com/yuuki/diamondb/pkg/web"
)

func init() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
}

func request(name string, timestamp int64, value float64, endpoint string) error {
	wr := &web.WriteRequest{
		Metric: &model.Metric{
			Name: name,
			Datapoints: []*model.Datapoint{
				{Timestamp: timestamp, Value: value},
			},
		},
	}
	jsonData := new(bytes.Buffer)
	json.NewEncoder(jsonData).Encode(wr)

	resp, err := http.Post(fmt.Sprintf("%s/datapoints", endpoint), "application/json", jsonData)
	if err != nil {
		return err
	}
	if resp.StatusCode != 204 {
		log.Printf("http request error (%s,%d,%f) %s\n", name, timestamp, value, resp.Status)
		return nil
	}
	log.Printf("http success (%s,%d,%f)\n", name, timestamp, value)
	return nil
}

func write(name string, n int, step int, start int64, endpoint string, concurrency int) {
	rand.Seed(time.Now().UnixNano())

	sem := make(chan struct{}, concurrency)
	var wg sync.WaitGroup
	for i := 0; i < n; i++ {
		wg.Add(1)
		i := i
		go func() {
			defer wg.Done()

		RETRY:
			select {
			case sem <- struct{}{}:
			default:
				time.Sleep(100 * time.Millisecond)
				goto RETRY
			}
			defer func() { <-sem }()

			timestamp := start + int64(step*i)
			value := rand.Float64() * 10.0
			if err := request(name, timestamp, value, endpoint); err != nil {
				log.Println(err)
			}
		}()
	}
	wg.Wait()
}

func main() {
	var (
		name        string
		n           int
		step        int
		start       string
		concurrency int
	)

	flags := flag.NewFlagSet("insert_test_datapoints", flag.ContinueOnError)
	flags.StringVar(&name, "name", "server1.loadavg5", "number of datapoints")
	flags.IntVar(&n, "num", 100, "number of datapoints")
	flags.IntVar(&step, "step", 60, "step")
	flags.StringVar(&start, "start", "now-1d", "start time (eg. now-1d)")
	flags.IntVar(&concurrency, "c", 1, "concurrency")

	if err := flags.Parse(os.Args[1:]); err != nil {
		log.Fatalln(err)
	}

	startTime, err := timeparser.ParseAtTime(start, nil)
	if err != nil {
		log.Fatalln(err)
	}

	if l := len(flags.Args()); l != 1 {
		log.Fatalf("the number of arguments must be 1, but %d", l)
	}
	endpoint := flags.Arg(0)

	write(name, n, step, startTime.Unix(), endpoint, concurrency)

	os.Exit(0)
}
<commit_msg>Fix help message<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"os"
	"sync"
	"time"

	"github.com/yuuki/diamondb/pkg/model"
	"github.com/yuuki/diamondb/pkg/timeparser"
	"github.com/yuuki/diamondb/pkg/web"
)

func init() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
}

func request(name string, timestamp int64, value float64, endpoint string) error {
	wr := &web.WriteRequest{
		Metric: &model.Metric{
			Name: name,
			Datapoints: []*model.Datapoint{
				{Timestamp: timestamp, Value: value},
			},
		},
	}
	jsonData := new(bytes.Buffer)
	json.NewEncoder(jsonData).Encode(wr)

	resp, err := http.Post(fmt.Sprintf("%s/datapoints", endpoint), "application/json", jsonData)
	if err != nil {
		return err
	}
	if resp.StatusCode != 204 {
		log.Printf("http request error (%s,%d,%f) %s\n", name, timestamp, value, resp.Status)
		return nil
	}
	log.Printf("http success (%s,%d,%f)\n", name, timestamp, value)
	return nil
}

func write(name string, n int, step int, start int64, endpoint string, concurrency int) {
	rand.Seed(time.Now().UnixNano())

	sem := make(chan struct{}, concurrency)
	var wg sync.WaitGroup
	for i := 0; i < n; i++ {
		wg.Add(1)
		i := i
		go func() {
			defer wg.Done()

		RETRY:
			select {
			case sem <- struct{}{}:
			default:
				time.Sleep(100 * time.Millisecond)
				goto RETRY
			}
			defer func() { <-sem }()

			timestamp := start + int64(step*i)
			value := rand.Float64() * 10.0
			if err := request(name, timestamp, value, endpoint); err != nil {
				log.Println(err)
			}
		}()
	}
	wg.Wait()
}

func main() {
	var (
		name        string
		n           int
		step        int
		start       string
		concurrency int
	)

	flags := flag.NewFlagSet("insert_test_datapoints", flag.ContinueOnError)
	flags.StringVar(&name, "name", "server1.loadavg5", "metric name")
	flags.IntVar(&n, "num", 100, "number of datapoints")
	flags.IntVar(&step, "step", 60, "step")
	flags.StringVar(&start, "start", "now-1d", "start time (eg. now-1d)")
	flags.IntVar(&concurrency, "c", 1, "concurrency")

	if err := flags.Parse(os.Args[1:]); err != nil {
		log.Fatalln(err)
	}

	startTime, err := timeparser.ParseAtTime(start, nil)
	if err != nil {
		log.Fatalln(err)
	}

	if l := len(flags.Args()); l != 1 {
		log.Fatalf("the number of arguments must be 1, but %d", l)
	}
	endpoint := flags.Arg(0)

	write(name, n, step, startTime.Unix(), endpoint, concurrency)

	os.Exit(0)
}
<|endoftext|>


<commit_before>// Copyright 2010 The GoGo Authors. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

//
// General code generation functions (registers, instructions, ...)
// Heavily depends on asm_out.go which represents the Plan9 assembly language
//

package main

import "./libgogo/_obj/libgogo"

// Currently register from R8-R15 are available for usage
var NumRegisters uint64 = 8;
var FreeRegisters [8]byte;

//
// Initialize the register to free-state.
//
func InitFreeRegisters() {
    var i uint64;
    for i = 0; i < NumRegisters; i = i + 1 {
        FreeRegisters[i] = 1;
    }
}

//
// Function returns a free register, BUT is not set to occupied.
//
func GetFreeRegister() uint64 {
    var i uint64;
    for i = 0; FreeRegisters[i] == 0; {
        i = i + 1;
        if i == NumRegisters {
            PrintHead();
            libgogo.ExitError("No more free registers available for code generation", 5);
        }
    }
    return i+8;
}

//
// Occupy a given register.
//
func OccupyRegister(index uint64) {
    var realIndex uint64;
    realIndex = index-8;
    FreeRegisters[realIndex] = 0;
}

//
// Free a given register.
//
func FreeRegister(index uint64) {
    var realIndex uint64;
    realIndex = index-8;
    FreeRegisters[realIndex] = 1;
}

//
// Saves the currently used registers to the stack
//
func SaveUsedRegisters() {
    var i uint64;
    for i = 0; i < NumRegisters; i = i + 1 {
        if FreeRegisters[i] == 0 {
            PrintInstruction_Reg("PUSH", 8, "R", i + 8, 0, 0, 0, "");
        }
    }
}

//
// Restores the currently used registers from the stack
//
func RestoreUsedRegisters() {
    var i uint64;
    for i = NumRegisters - 1; i >= 0; i = i - 1 { //Reverse order (stack!)
        if FreeRegisters[i] == 0 {
            PrintInstruction_Reg("POP", 8, "R", i + 8, 0, 0, 0, "");
            FreeRegisters[i] = 1;
        }
        if i == 0 { //Break on i = 0 as i-1 on uint64 yields to underflow
            break;
        }
    }
}

//
// Frees the register occupied by the given item if applicable.
// Freeing is only possible if the mode is registered.
//
func FreeRegisterIfRequired(item *libgogo.Item) {
    if item.Mode == libgogo.MODE_REG {
        FreeRegister(item.R);
        if item.C != 0 {
            FreeRegister(item.C);
        }
    }
}

//
// Moves the value of the address a register is currently pointing to into the register itself
//
func DereferRegisterIfNecessary(item *libgogo.Item) {
    var opsize uint64;
    var retVal uint64;
    if (item.Mode == libgogo.MODE_REG) && (item.A != 0) { //Derefer register if it contains an address
        item.A = 0; //Register will soon contain a value; make sure op size calculation is based on the actual type size, not on the pointer size
        opsize = GetOpSize(item, "MOV");
        retVal = PrintInstruction_Reg_Reg("MOV", opsize, "R", item.R, 1, 0, 0, "", "R", item.R, 0, 0, 0, ""); //MOV (item.R), item.R
        if retVal != 0 {
            retVal = GetFreeRegister(); //Additional register required
            OccupyRegister(retVal);
            item.C = retVal;
            PrintInstruction_Reg_Reg("MOV", retVal, "R", item.R, 1, 8, 0, "", "R", item.C, 0, 0, 0, ""); //MOV 8(item.R), item.C
        }
    }
}

//
// Derefers the item given if its type is a pointer
//
func DereferItemIfNecessary(item *libgogo.Item) {
    var oldA uint64;
    var opsize uint64;
    var retVal uint64;
    if item.PtrType == 1 {
        if item.Mode == libgogo.MODE_REG { //Item is already in a register => derefer register
            opsize = GetOpSize(item, "MOV");
            retVal = PrintInstruction_Reg_Reg("MOV", opsize, "R", item.R, 1, 0, 0, "", "R", item.R, 0, 0, 0, ""); //MOV (item.R), item.R
            if retVal != 0 {
                retVal = GetFreeRegister(); //Additional register required
                OccupyRegister(retVal);
                item.C = retVal;
                PrintInstruction_Reg_Reg("MOV", retVal, "R", item.R, 1, 8, 0, "", "R", item.C, 0, 0, 0, ""); //MOV 8(item.R), item.C
            }
        } else { //Item is not a register yet => make it a register by loading its value
            oldA = item.A; //Save value of A
            MakeRegistered(item, 0); //Don't load address as loading the value automatically derefers the item
            item.A = oldA; //Restore old value of A
        }
        item.PtrType = 0; //Item type is no longer a pointer
    }
}

//
// Simple wrapper to asm_out printing
//
func GenerateComment(msg string) {
    var str string = "";
    var tmpPtr *string;
    var temp string;
    if DEBUG_LEVEL >= 10 {
        tmpPtr = &DataSegment;
        if (OutputStringPtr != tmpPtr) {
            str = "  //--- ";
        } else { //No indentation in data segment
            str = "//--- ";
        }
        libgogo.StringAppend(&str, msg);
        libgogo.StringAppend(&str, " at ");
        temp = BuildHead();
        libgogo.StringAppend(&str, temp);
        libgogo.StringAppend(&str, "\n");
        PrintCodeOutput(str);
    }
}

func GenerateFieldAccess(item *libgogo.Item, offset uint64) {
    var offsetItem *libgogo.Item;
    if Compile != 0 {
        DereferItemIfNecessary(item); //Derefer address if item is a pointer
        if item.Mode == libgogo.MODE_VAR { //Variable
            if item.Global == 0 { //Local variable offset calculation
                item.A = item.A - offset; //Reverse order due to sign (p.e. -24(SP) with offset 16 is to be -8(SP) and thus 24-16)
            } else { //Global variable offset calculation
                item.A = item.A + offset;
            }
        } else { //Register
            offsetItem = libgogo.NewItem(); //For direct and indirect offset calculation
            libgogo.SetItem(offsetItem, libgogo.MODE_CONST, uint64_t, 0, offset, 0, 0); //Constant item for offset
            AddSubInstruction("ADD", item, offsetItem, 0, 1); //Add constant item (offset), calculating with addresses
        }
    }
}

func GenerateVariableFieldAccess(item *libgogo.Item, offsetItem *libgogo.Item, baseTypeSize uint64) {
    var sizeItem *libgogo.Item;
    if Compile != 0 {
        DereferItemIfNecessary(item); //Derefer address if item is a pointer
        if (offsetItem.Itemtype != byte_t) && (offsetItem.Itemtype != uint64_t) {
            SymbolTableError("Invalid index type for", "", "array access:", offsetItem.Itemtype.Name);
        }
        sizeItem = libgogo.NewItem();
        libgogo.SetItem(sizeItem, libgogo.MODE_CONST, uint64_t, 0, baseTypeSize, 0, 0); //Constant item
        DivMulInstruction("MUL", offsetItem, sizeItem, 0, 1); //Multiply identifier value by array base type size => offsetItem now constains the field offset
        AddSubInstruction("ADD", item, offsetItem, 0, 1); //Add calculated offset to base address
    }
}

//
// Function converts a given item to registered mode if it is not already
// a register. This function does not check whether the item is a pointer type!
//
func MakeRegistered(item *libgogo.Item, calculatewithaddresses uint64) {
    var reg uint64;
    var reg2 uint64;
    var opsize uint64;
    if item.Mode != libgogo.MODE_REG {
        reg = GetFreeRegister();
        OccupyRegister(reg);

        if item.Mode == libgogo.MODE_CONST { // const item
            opsize = GetOpSize(item, "MOV");
            PrintInstruction_Imm_Reg("MOV", opsize, item.A, "R", reg, 0, 0, 0, ""); // MOV $item.A, Rdone (soon to be item.R)
        } else { // var item
            if calculatewithaddresses == 0 {
                opsize = GetOpSize(item, "MOV");
                if opsize > 8 { //Occupy additional register if operand size is higher than 8 bytes
                    reg2 = GetFreeRegister();
                    OccupyRegister(reg2);
                    item.C = reg2;
                }
                PrintInstruction_Var_Reg("MOV", item, "R", reg, "R", reg2); // MOV item.A(SB), Rdone (soon to be item.R)
            } else {
                opsize = GetOpSize(item, "LEA");
                PrintInstruction_Var_Reg("LEA", item, "R", reg, "", 0); // LEA item.A(SB), Rdone (soon to be item.R)
            }
        }

        item.Mode = libgogo.MODE_REG;
        item.R = reg; // item is now a register
        item.A = calculatewithaddresses; // item now contains a value if calculatewithaddresses is 0, or an address if calculatewithaddress is 1
    }
}

//
// Constant folding function. If both items are constants the operation can be
// done in the compiler.
//
func ConstFolding(item1 *libgogo.Item, item2 *libgogo.Item, constvalue uint64) uint64 {
    var boolFlag uint64 = 0;
    if (item1.Mode == libgogo.MODE_CONST) && (item2.Mode == libgogo.MODE_CONST) {
        item1.A = constvalue;
        boolFlag = 1;
    }
    return boolFlag;
}
<commit_msg>codegen.go: Emergency revert of previous register leak hotfix as it turned out to be plain wrong (see mail for details)<commit_after>// Copyright 2010 The GoGo Authors. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

//
// General code generation functions (registers, instructions, ...)
// Heavily depends on asm_out.go which represents the Plan9 assembly language
//

package main

import "./libgogo/_obj/libgogo"

// Currently register from R8-R15 are available for usage
var NumRegisters uint64 = 8;
var FreeRegisters [8]byte;

//
// Initialize the register to free-state.
//
func InitFreeRegisters() {
    var i uint64;
    for i = 0; i < NumRegisters; i = i + 1 {
        FreeRegisters[i] = 1;
    }
}

//
// Function returns a free register, BUT is not set to occupied.
//
func GetFreeRegister() uint64 {
    var i uint64;
    for i = 0; FreeRegisters[i] == 0; {
        i = i + 1;
        if i == NumRegisters {
            PrintHead();
            libgogo.ExitError("No more free registers available for code generation", 5);
        }
    }
    return i+8;
}

//
// Occupy a given register.
//
func OccupyRegister(index uint64) {
    var realIndex uint64;
    realIndex = index-8;
    FreeRegisters[realIndex] = 0;
}

//
// Free a given register.
//
func FreeRegister(index uint64) {
    var realIndex uint64;
    realIndex = index-8;
    FreeRegisters[realIndex] = 1;
}

//
// Saves the currently used registers to the stack
//
func SaveUsedRegisters() {
    var i uint64;
    for i = 0; i < NumRegisters; i = i + 1 {
        if FreeRegisters[i] == 0 {
            PrintInstruction_Reg("PUSH", 8, "R", i + 8, 0, 0, 0, "");
        }
    }
}

//
// Restores the currently used registers from the stack
//
func RestoreUsedRegisters() {
    var i uint64;
    for i = NumRegisters - 1; i >= 0; i = i - 1 { //Reverse order (stack!)
        if FreeRegisters[i] == 0 {
            PrintInstruction_Reg("POP", 8, "R", i + 8, 0, 0, 0, "");
        }
        if i == 0 { //Break on i = 0 as i-1 on uint64 yields to underflow
            break;
        }
    }
}

//
// Frees the register occupied by the given item if applicable.
// Freeing is only possible if the mode is registered.
//
func FreeRegisterIfRequired(item *libgogo.Item) {
    if item.Mode == libgogo.MODE_REG {
        FreeRegister(item.R);
        if item.C != 0 {
            FreeRegister(item.C);
        }
    }
}

//
// Moves the value of the address a register is currently pointing to into the register itself
//
func DereferRegisterIfNecessary(item *libgogo.Item) {
    var opsize uint64;
    var retVal uint64;
    if (item.Mode == libgogo.MODE_REG) && (item.A != 0) { //Derefer register if it contains an address
        item.A = 0; //Register will soon contain a value; make sure op size calculation is based on the actual type size, not on the pointer size
        opsize = GetOpSize(item, "MOV");
        retVal = PrintInstruction_Reg_Reg("MOV", opsize, "R", item.R, 1, 0, 0, "", "R", item.R, 0, 0, 0, ""); //MOV (item.R), item.R
        if retVal != 0 {
            retVal = GetFreeRegister(); //Additional register required
            OccupyRegister(retVal);
            item.C = retVal;
            PrintInstruction_Reg_Reg("MOV", retVal, "R", item.R, 1, 8, 0, "", "R", item.C, 0, 0, 0, ""); //MOV 8(item.R), item.C
        }
    }
}

//
// Derefers the item given if its type is a pointer
//
func DereferItemIfNecessary(item *libgogo.Item) {
    var oldA uint64;
    var opsize uint64;
    var retVal uint64;
    if item.PtrType == 1 {
        if item.Mode == libgogo.MODE_REG { //Item is already in a register => derefer register
            opsize = GetOpSize(item, "MOV");
            retVal = PrintInstruction_Reg_Reg("MOV", opsize, "R", item.R, 1, 0, 0, "", "R", item.R, 0, 0, 0, ""); //MOV (item.R), item.R
            if retVal != 0 {
                retVal = GetFreeRegister(); //Additional register required
                OccupyRegister(retVal);
                item.C = retVal;
                PrintInstruction_Reg_Reg("MOV", retVal, "R", item.R, 1, 8, 0, "", "R", item.C, 0, 0, 0, ""); //MOV 8(item.R), item.C
            }
        } else { //Item is not a register yet => make it a register by loading its value
            oldA = item.A; //Save value of A
            MakeRegistered(item, 0); //Don't load address as loading the value automatically derefers the item
            item.A = oldA; //Restore old value of A
        }
        item.PtrType = 0; //Item type is no longer a pointer
    }
}

//
// Simple wrapper to asm_out printing
//
func GenerateComment(msg string) {
    var str string = "";
    var tmpPtr *string;
    var temp string;
    if DEBUG_LEVEL >= 10 {
        tmpPtr = &DataSegment;
        if (OutputStringPtr != tmpPtr) {
            str = "  //--- ";
        } else { //No indentation in data segment
            str = "//--- ";
        }
        libgogo.StringAppend(&str, msg);
        libgogo.StringAppend(&str, " at ");
        temp = BuildHead();
        libgogo.StringAppend(&str, temp);
        libgogo.StringAppend(&str, "\n");
        PrintCodeOutput(str);
    }
}

func GenerateFieldAccess(item *libgogo.Item, offset uint64) {
    var offsetItem *libgogo.Item;
    if Compile != 0 {
        DereferItemIfNecessary(item); //Derefer address if item is a pointer
        if item.Mode == libgogo.MODE_VAR { //Variable
            if item.Global == 0 { //Local variable offset calculation
                item.A = item.A - offset; //Reverse order due to sign (p.e. -24(SP) with offset 16 is to be -8(SP) and thus 24-16)
            } else { //Global variable offset calculation
                item.A = item.A + offset;
            }
        } else { //Register
            offsetItem = libgogo.NewItem(); //For direct and indirect offset calculation
            libgogo.SetItem(offsetItem, libgogo.MODE_CONST, uint64_t, 0, offset, 0, 0); //Constant item for offset
            AddSubInstruction("ADD", item, offsetItem, 0, 1); //Add constant item (offset), calculating with addresses
        }
    }
}

func GenerateVariableFieldAccess(item *libgogo.Item, offsetItem *libgogo.Item, baseTypeSize uint64) {
    var sizeItem *libgogo.Item;
    if Compile != 0 {
        DereferItemIfNecessary(item); //Derefer address if item is a pointer
        if (offsetItem.Itemtype != byte_t) && (offsetItem.Itemtype != uint64_t) {
            SymbolTableError("Invalid index type for", "", "array access:", offsetItem.Itemtype.Name);
        }
        sizeItem = libgogo.NewItem();
        libgogo.SetItem(sizeItem, libgogo.MODE_CONST, uint64_t, 0, baseTypeSize, 0, 0); //Constant item
        DivMulInstruction("MUL", offsetItem, sizeItem, 0, 1); //Multiply identifier value by array base type size => offsetItem now constains the field offset
        AddSubInstruction("ADD", item, offsetItem, 0, 1); //Add calculated offset to base address
    }
}

//
// Function converts a given item to registered mode if it is not already
// a register. This function does not check whether the item is a pointer type!
//
func MakeRegistered(item *libgogo.Item, calculatewithaddresses uint64) {
    var reg uint64;
    var reg2 uint64;
    var opsize uint64;
    if item.Mode != libgogo.MODE_REG {
        reg = GetFreeRegister();
        OccupyRegister(reg);

        if item.Mode == libgogo.MODE_CONST { // const item
            opsize = GetOpSize(item, "MOV");
            PrintInstruction_Imm_Reg("MOV", opsize, item.A, "R", reg, 0, 0, 0, ""); // MOV $item.A, Rdone (soon to be item.R)
        } else { // var item
            if calculatewithaddresses == 0 {
                opsize = GetOpSize(item, "MOV");
                if opsize > 8 { //Occupy additional register if operand size is higher than 8 bytes
                    reg2 = GetFreeRegister();
                    OccupyRegister(reg2);
                    item.C = reg2;
                }
                PrintInstruction_Var_Reg("MOV", item, "R", reg, "R", reg2); // MOV item.A(SB), Rdone (soon to be item.R)
            } else {
                opsize = GetOpSize(item, "LEA");
                PrintInstruction_Var_Reg("LEA", item, "R", reg, "", 0); // LEA item.A(SB), Rdone (soon to be item.R)
            }
        }

        item.Mode = libgogo.MODE_REG;
        item.R = reg; // item is now a register
        item.A = calculatewithaddresses; // item now contains a value if calculatewithaddresses is 0, or an address if calculatewithaddress is 1
    }
}

//
// Constant folding function. If both items are constants the operation can be
// done in the compiler.
//
func ConstFolding(item1 *libgogo.Item, item2 *libgogo.Item, constvalue uint64) uint64 {
    var boolFlag uint64 = 0;
    if (item1.Mode == libgogo.MODE_CONST) && (item2.Mode == libgogo.MODE_CONST) {
        item1.A = constvalue;
        boolFlag = 1;
    }
    return boolFlag;
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"strings"

	. "github.com/dave/jennifer/jen"
)

func render(w io.Writer) error {
	file := NewFile("jen")

	file.Comment("\tThis file is generated by genjen - do not edit!\n")
	file.Line()

	for _, b := range groups {
		b := b // b used in closures
		if b.name == "" {
			continue
		}
		comment := Commentf("%s %s", b.name, b.comment)

		if b.variadic && len(b.parameters) > 1 {
			panic("should not have variadic function with multiple params")
		}

		var variadic Code
		if b.variadic {
			variadic = Op("...")
		}
		var funcParams []Code
		var callParams []Code
		for _, name := range b.parameters {
			funcParams = append(funcParams, Id(name).Add(variadic).Id("Code"))
			callParams = append(callParams, Id(name).Add(variadic))
		}

		addFunctionAndGroupMethod(
			file,
			b.name,
			comment,
			funcParams,
			callParams,
		)

		/*
			// <comment>
			func (s *Statement) <name>(<funcParams>) *Statement {
				g := &Group{
					items:     []Code{<paramNames>}|<paramNames[0]>,
					name:      "<name>",
					open:      "<opening>",
					close:     "<closing>",
					separator: "<separator>",
				}
				*s = append(*s, g)
				return s
			}
		*/
		file.Add(comment)
		file.Func().Params(
			Id("s").Op("*").Id("Statement"),
		).Id(b.name).Params(
			funcParams...,
		).Op("*").Id("Statement").Block(
			Id("g").Op(":=").Op("&").Id("Group").Values(Dict{
				Id("items"): Do(func(s *Statement) {
					if b.variadic {
						s.Id(b.parameters[0])
					} else {
						s.Index().Id("Code").ValuesFunc(func(g *Group) {
							for _, name := range b.parameters {
								g.Id(name)
							}
						})
					}
				}),
				Id("name"):      Lit(strings.ToLower(b.name)),
				Id("open"):      Lit(b.opening),
				Id("close"):     Lit(b.closing),
				Id("separator"): Lit(b.separator),
			}),
			Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("g")),
			Return(Id("s")),
		)

		funcComment := Commentf("%sFunc %s", b.name, b.comment)
		funcFuncParams := []Code{Id("f").Func().Params(Op("*").Id("Group"))}
		funcCallParams := []Code{Id("f")}

		if b.variadic && !b.preventFunc {
			funcName := b.name + "Func"
			addFunctionAndGroupMethod(
				file,
				funcName,
				funcComment,
				funcFuncParams,
				funcCallParams,
			)

			/*
				// <funcComment>
				func (s *Statement) <funcName>(f func(*Group)) *Statement {
					g := &Group{
						name:      "<name>",
						open:      "<opening>",
						close:     "<closing>",
						separator: "<separator>",
					}
					f(g)
					*s = append(*s, g)
					return s
				}
			*/
			file.Add(funcComment)
			file.Func().Params(
				Id("s").Op("*").Id("Statement"),
			).Id(funcName).Params(
				funcFuncParams...,
			).Op("*").Id("Statement").Block(
				Id("g").Op(":=").Op("&").Id("Group").Values(Dict{
					Id("name"):      Lit(strings.ToLower(b.name)),
					Id("open"):      Lit(b.opening),
					Id("close"):     Lit(b.closing),
					Id("separator"): Lit(b.separator),
				}),
				Id("f").Call(Id("g")),
				Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("g")),
				Return(Id("s")),
			)
		}
	}

	type tkn struct {
		token     string
		name      string
		tokenType string
		tokenDesc string
	}
	tokens := []tkn{}
	for _, v := range identifiers {
		tokens = append(tokens, tkn{
			token:     v,
			name:      strings.ToUpper(v[:1]) + v[1:],
			tokenType: "identifierToken",
			tokenDesc: "identifier",
		})
	}
	for _, v := range keywords {
		tokens = append(tokens, tkn{
			token:     v,
			name:      strings.ToUpper(v[:1]) + v[1:],
			tokenType: "keywordToken",
			tokenDesc: "keyword",
		})
	}

	for _, t := range tokens {
		t := t // used in closures
		comment := Commentf(
			"%s renders the %s %s.",
			t.name,
			t.token,
			t.tokenDesc,
		)
		addFunctionAndGroupMethod(
			file,
			t.name,
			comment,
			nil,
			nil,
		)

		/*
			// <comment>
			func (s *Statement) <name>() *Statement {
				t := token{
					typ:     <tokenType>,
					content: "<token>",
				}
				*s = append(*s, t)
				return s
			}
		*/
		file.Add(comment)
		file.Func().Params(
			Id("s").Op("*").Id("Statement"),
		).Id(t.name).Params().Op("*").Id("Statement").Block(
			Id("t").Op(":=").Id("token").Values(Dict{
				Id("typ"):     Id(t.tokenType),
				Id("content"): Lit(t.token),
			}),
			Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("t")),
			Return(Id("s")),
		)
	}

	return file.Render(w)
}

// For each method on *Statement, this this generates a package level
// function and a method on *Group, both with the same name.
func addFunctionAndGroupMethod(
	file *File,
	name string,
	comment *Statement,
	funcParams []Code,
	callParams []Code,
) {
	/*
		// <comment>
		func <name>(<funcParams>) *Statement {
			return newStatement().<name>(<callParams>)
		}
	*/
	file.Add(comment)
	file.Func().Id(name).Params(funcParams...).Op("*").Id("Statement").Block(
		Return(Id("newStatement").Call().Dot(name).Call(callParams...)),
	)
	/*
		// <comment>
		func (g *Group) <name>(<funcParams>) *Statement {
			s := <name>(<callParams>)
			g.items = append(g.items, s)
			return s
		}
	*/
	file.Add(comment)
	file.Func().Params(
		Id("g").Op("*").Id("Group"),
	).Id(name).Params(funcParams...).Op("*").Id("Statement").Block(
		Id("s").Op(":=").Id(name).Params(callParams...),
		Id("g").Dot("items").Op("=").Append(Id("g").Dot("items"), Id("s")),
		Return(Id("s")),
	)
}
<commit_msg>Reorganise genjen<commit_after>package main

import (
	"io"
	"strings"

	. "github.com/dave/jennifer/jen"
)

func render(w io.Writer) error {
	file := NewFile("jen")

	file.Comment("\tThis file is generated by genjen - do not edit!\n")
	file.Line()

	for _, b := range groups {
		b := b // b used in closures
		if b.name == "" {
			continue
		}
		comment := Commentf("%s %s", b.name, b.comment)

		if b.variadic && len(b.parameters) > 1 {
			panic("should not have variadic function with multiple params")
		}

		var variadic Code
		if b.variadic {
			variadic = Op("...")
		}
		var funcParams []Code
		var callParams []Code
		for _, name := range b.parameters {
			funcParams = append(funcParams, Id(name).Add(variadic).Id("Code"))
			callParams = append(callParams, Id(name).Add(variadic))
		}

		addFunctionAndGroupMethod(
			file,
			b.name,
			comment,
			funcParams,
			callParams,
		)

		/*
			// <comment>
			func (s *Statement) <name>(<funcParams>) *Statement {
				g := &Group{
					items:     []Code{<paramNames>}|<paramNames[0]>,
					name:      "<name>",
					open:      "<opening>",
					close:     "<closing>",
					separator: "<separator>",
				}
				*s = append(*s, g)
				return s
			}
		*/
		file.Add(comment)
		file.Func().Params(
			Id("s").Op("*").Id("Statement"),
		).Id(b.name).Params(
			funcParams...,
		).Op("*").Id("Statement").Block(
			Id("g").Op(":=").Op("&").Id("Group").Values(Dict{
				Id("items"): Do(func(s *Statement) {
					if b.variadic {
						s.Id(b.parameters[0])
					} else {
						s.Index().Id("Code").ValuesFunc(func(g *Group) {
							for _, name := range b.parameters {
								g.Id(name)
							}
						})
					}
				}),
				Id("name"):      Lit(strings.ToLower(b.name)),
				Id("open"):      Lit(b.opening),
				Id("close"):     Lit(b.closing),
				Id("separator"): Lit(b.separator),
			}),
			Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("g")),
			Return(Id("s")),
		)

		if b.variadic && !b.preventFunc {

			funcName := b.name + "Func"
			funcComment := Commentf("%sFunc %s", b.name, b.comment)
			funcFuncParams := []Code{Id("f").Func().Params(Op("*").Id("Group"))}
			funcCallParams := []Code{Id("f")}

			addFunctionAndGroupMethod(
				file,
				funcName,
				funcComment,
				funcFuncParams,
				funcCallParams,
			)

			/*
				// <funcComment>
				func (s *Statement) <funcName>(f func(*Group)) *Statement {
					g := &Group{
						name:      "<name>",
						open:      "<opening>",
						close:     "<closing>",
						separator: "<separator>",
					}
					f(g)
					*s = append(*s, g)
					return s
				}
			*/
			file.Add(funcComment)
			file.Func().Params(
				Id("s").Op("*").Id("Statement"),
			).Id(funcName).Params(
				funcFuncParams...,
			).Op("*").Id("Statement").Block(
				Id("g").Op(":=").Op("&").Id("Group").Values(Dict{
					Id("name"):      Lit(strings.ToLower(b.name)),
					Id("open"):      Lit(b.opening),
					Id("close"):     Lit(b.closing),
					Id("separator"): Lit(b.separator),
				}),
				Id("f").Call(Id("g")),
				Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("g")),
				Return(Id("s")),
			)
		}
	}

	type tkn struct {
		token     string
		name      string
		tokenType string
		tokenDesc string
	}
	tokens := []tkn{}
	for _, v := range identifiers {
		tokens = append(tokens, tkn{
			token:     v,
			name:      strings.ToUpper(v[:1]) + v[1:],
			tokenType: "identifierToken",
			tokenDesc: "identifier",
		})
	}
	for _, v := range keywords {
		tokens = append(tokens, tkn{
			token:     v,
			name:      strings.ToUpper(v[:1]) + v[1:],
			tokenType: "keywordToken",
			tokenDesc: "keyword",
		})
	}

	for _, t := range tokens {
		t := t // used in closures
		comment := Commentf(
			"%s renders the %s %s.",
			t.name,
			t.token,
			t.tokenDesc,
		)
		addFunctionAndGroupMethod(
			file,
			t.name,
			comment,
			nil,
			nil,
		)

		/*
			// <comment>
			func (s *Statement) <name>() *Statement {
				t := token{
					typ:     <tokenType>,
					content: "<token>",
				}
				*s = append(*s, t)
				return s
			}
		*/
		file.Add(comment)
		file.Func().Params(
			Id("s").Op("*").Id("Statement"),
		).Id(t.name).Params().Op("*").Id("Statement").Block(
			Id("t").Op(":=").Id("token").Values(Dict{
				Id("typ"):     Id(t.tokenType),
				Id("content"): Lit(t.token),
			}),
			Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("t")),
			Return(Id("s")),
		)
	}

	return file.Render(w)
}

// For each method on *Statement, this this generates a package level
// function and a method on *Group, both with the same name.
func addFunctionAndGroupMethod(
	file *File,
	name string,
	comment *Statement,
	funcParams []Code,
	callParams []Code,
) {
	/*
		// <comment>
		func <name>(<funcParams>) *Statement {
			return newStatement().<name>(<callParams>)
		}
	*/
	file.Add(comment)
	file.Func().Id(name).Params(funcParams...).Op("*").Id("Statement").Block(
		Return(Id("newStatement").Call().Dot(name).Call(callParams...)),
	)
	/*
		// <comment>
		func (g *Group) <name>(<funcParams>) *Statement {
			s := <name>(<callParams>)
			g.items = append(g.items, s)
			return s
		}
	*/
	file.Add(comment)
	file.Func().Params(
		Id("g").Op("*").Id("Group"),
	).Id(name).Params(funcParams...).Op("*").Id("Statement").Block(
		Id("s").Op(":=").Id(name).Params(callParams...),
		Id("g").Dot("items").Op("=").Append(Id("g").Dot("items"), Id("s")),
		Return(Id("s")),
	)
}
<|endoftext|>


<commit_before>package api

import (
	"net/http"
	"strings"

	"github.com/ViBiOh/auth/pkg/auth"
	"github.com/ViBiOh/dashboard/pkg/deploy"
	"github.com/ViBiOh/dashboard/pkg/docker"
	"github.com/ViBiOh/httputils/pkg/httperror"
)

const (
	containersPrefix = `/containers`
	deployPrefix     = `/deploy`
)

// App stores informations
type App struct {
	authApp   *auth.App
	dockerApp *docker.App
	deployApp *deploy.App
}

// NewApp creates new App from dependencies
func NewApp(authApp *auth.App, dockerApp *docker.App, deployApp *deploy.App) *App {
	return &App{
		authApp:   authApp,
		dockerApp: dockerApp,
		deployApp: deployApp,
	}
}

// Handler for Docker request. Should be use with net/http
func (a *App) Handler() http.Handler {
	containerHandler := http.StripPrefix(containersPrefix, a.dockerApp.Handler())
	deployHandler := http.StripPrefix(deployPrefix, a.deployApp.Handler())

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodOptions {
			if _, err := w.Write(nil); err != nil {
				httperror.InternalServerError(w, err)
			}
			return
		}

		if strings.HasPrefix(r.URL.Path, containersPrefix) {
			containerHandler.ServeHTTP(w, r)
			return
		}

		if strings.HasPrefix(r.URL.Path, deployPrefix) {
			deployHandler.ServeHTTP(w, r)
			return
		}

		httperror.NotFound(w)
	})
}

// HealthcheckHandler for Healthcheck request. Should be use with net/http
func (a *App) HealthcheckHandler() http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if a.dockerApp == nil {
			w.WriteHeader(http.StatusServiceUnavailable)
			return
		}

		if !a.dockerApp.Healthcheck() {
			w.WriteHeader(http.StatusServiceUnavailable)
			return
		}

		w.WriteHeader(http.StatusOK)
	})
}
<commit_msg>Removing unecessary modifier<commit_after>package api

import (
	"net/http"
	"strings"

	"github.com/ViBiOh/auth/pkg/auth"
	"github.com/ViBiOh/dashboard/pkg/deploy"
	"github.com/ViBiOh/dashboard/pkg/docker"
	"github.com/ViBiOh/httputils/pkg/httperror"
)

const (
	containersPrefix = `/containers`
	deployPrefix     = `/deploy`
)

// App stores informations
type App struct {
	authApp   *auth.App
	dockerApp *docker.App
	deployApp *deploy.App
}

// NewApp creates new App from dependencies
func NewApp(authApp *auth.App, dockerApp *docker.App, deployApp *deploy.App) *App {
	return &App{
		authApp:   authApp,
		dockerApp: dockerApp,
		deployApp: deployApp,
	}
}

// Handler for Docker request. Should be use with net/http
func (a App) Handler() http.Handler {
	containerHandler := http.StripPrefix(containersPrefix, a.dockerApp.Handler())
	deployHandler := http.StripPrefix(deployPrefix, a.deployApp.Handler())

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodOptions {
			if _, err := w.Write(nil); err != nil {
				httperror.InternalServerError(w, err)
			}
			return
		}

		if strings.HasPrefix(r.URL.Path, containersPrefix) {
			containerHandler.ServeHTTP(w, r)
			return
		}

		if strings.HasPrefix(r.URL.Path, deployPrefix) {
			deployHandler.ServeHTTP(w, r)
			return
		}

		httperror.NotFound(w)
	})
}

// HealthcheckHandler for Healthcheck request. Should be use with net/http
func (a App) HealthcheckHandler() http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if a.dockerApp == nil {
			w.WriteHeader(http.StatusServiceUnavailable)
			return
		}

		if !a.dockerApp.Healthcheck() {
			w.WriteHeader(http.StatusServiceUnavailable)
			return
		}

		w.WriteHeader(http.StatusOK)
	})
}
<|endoftext|>


<commit_before>// +build linux

package water

import (
	"os"
	"strings"
	"syscall"
	"unsafe"
)

const (
	cIFF_TUN   = 0x0001
	cIFF_TAP   = 0x0002
	cIFF_NO_PI = 0x1000
)

type ifReq struct {
	Name  [0x10]byte
	Flags uint16
	pad   [0x28 - 0x10 - 2]byte
}

func ioctl(fd uintptr, request int, argp uintptr) error {
	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(request), argp)
	if errno != 0 {
		return os.NewSyscallError("ioctl", errno)
	}
	return nil
}

func newTAP(config Config) (ifce *Interface, err error) {
	file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}
	name, err := createInterface(file.Fd(), config.Name, cIFF_TAP|cIFF_NO_PI)
	if err != nil {
		return nil, err
	}

	// Set Device Owner
	if config.Owner >= 0 {
		if err = ioctl(file.Fd(), syscall.TUNSETOWNER, uintptr(config.Owner)); err != nil {
			return
		}
	}

	// Set Device Group
	if config.Group >= 0 {
		if err = ioctl(file.Fd(), syscall.TUNSETGROUP, uintptr(config.Group)); err != nil {
			return
		}
	}

	// Set/Clear Persist Device Flag
	if err = setPersistence(file.Fd(), config.Persist); err != nil {
		return
	}

	ifce = &Interface{isTAP: true, ReadWriteCloser: file, name: name}
	return
}

func newTUN(config Config) (ifce *Interface, err error) {
	file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}
	name, err := createInterface(file.Fd(), config.Name, cIFF_TUN|cIFF_NO_PI)
	if err != nil {
		return nil, err
	}

	// Set Device Owner
	if config.Owner >= 0 {
		if err = ioctl(file.Fd(), syscall.TUNSETOWNER, uintptr(config.Owner)); err != nil {
			return
		}
	}

	// Set Device Group
	if config.Group >= 0 {
		if err = ioctl(file.Fd(), syscall.TUNSETGROUP, uintptr(config.Group)); err != nil {
			return
		}
	}

	// Set/Clear Persist Device Flag
	if err = setPersistence(file.Fd(), config.Persist); err != nil {
		return
	}

	ifce = &Interface{isTAP: false, ReadWriteCloser: file, name: name}
	return
}

func createInterface(fd uintptr, ifName string, flags uint16) (createdIFName string, err error) {
	var req ifReq
	req.Flags = flags
	copy(req.Name[:], ifName)

	err = ioctl(fd, syscall.TUNSETIFF, uintptr(unsafe.Pointer(&req)))
	if err != nil {
		return
	}

	createdIFName = strings.Trim(string(req.Name[:]), "\x00")
	return
}

func setPersistence(fd uintptr, enabled bool) error {
	value := 0;
	if enabled {
		value = 1
	}
	return ioctl(fd, syscall.TUNSETPERSIST, uintptr(value))
}
<commit_msg>Removes Redundant Type Conversion<commit_after>// +build linux

package water

import (
	"os"
	"strings"
	"syscall"
	"unsafe"
)

const (
	cIFF_TUN   = 0x0001
	cIFF_TAP   = 0x0002
	cIFF_NO_PI = 0x1000
)

type ifReq struct {
	Name  [0x10]byte
	Flags uint16
	pad   [0x28 - 0x10 - 2]byte
}

func ioctl(fd uintptr, request int, argp uintptr) error {
	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(request), argp)
	if errno != 0 {
		return os.NewSyscallError("ioctl", errno)
	}
	return nil
}

func newTAP(config Config) (ifce *Interface, err error) {
	file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}
	name, err := createInterface(file.Fd(), config.Name, cIFF_TAP|cIFF_NO_PI)
	if err != nil {
		return nil, err
	}

	// Set Device Owner
	if config.Owner >= 0 {
		if err = ioctl(file.Fd(), syscall.TUNSETOWNER, uintptr(config.Owner)); err != nil {
			return
		}
	}

	// Set Device Group
	if config.Group >= 0 {
		if err = ioctl(file.Fd(), syscall.TUNSETGROUP, uintptr(config.Group)); err != nil {
			return
		}
	}

	// Set/Clear Persist Device Flag
	if err = setPersistence(file.Fd(), config.Persist); err != nil {
		return
	}

	ifce = &Interface{isTAP: true, ReadWriteCloser: file, name: name}
	return
}

func newTUN(config Config) (ifce *Interface, err error) {
	file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}
	name, err := createInterface(file.Fd(), config.Name, cIFF_TUN|cIFF_NO_PI)
	if err != nil {
		return nil, err
	}

	// Set Device Owner
	if config.Owner >= 0 {
		if err = ioctl(file.Fd(), syscall.TUNSETOWNER, uintptr(config.Owner)); err != nil {
			return
		}
	}

	// Set Device Group
	if config.Group >= 0 {
		if err = ioctl(file.Fd(), syscall.TUNSETGROUP, uintptr(config.Group)); err != nil {
			return
		}
	}

	// Set/Clear Persist Device Flag
	if err = setPersistence(file.Fd(), config.Persist); err != nil {
		return
	}

	ifce = &Interface{isTAP: false, ReadWriteCloser: file, name: name}
	return
}

func createInterface(fd uintptr, ifName string, flags uint16) (createdIFName string, err error) {
	var req ifReq
	req.Flags = flags
	copy(req.Name[:], ifName)

	err = ioctl(fd, syscall.TUNSETIFF, uintptr(unsafe.Pointer(&req)))
	if err != nil {
		return
	}

	createdIFName = strings.Trim(string(req.Name[:]), "\x00")
	return
}

func setPersistence(fd uintptr, enabled bool) error {
	value := 0;
	if enabled {
		value = 1
	}
	return ioctl(fd, syscall.TUNSETPERSIST, uintptr(value))
}
<|endoftext|>