<commit_before>// Package store uses an Interface to automatically store information in a sqlite database
package store

import (
	"io"
	"sync"

	"github.com/mxk/go-sqlite/sqlite3"
)

const (
	add = iota
	get
	update
	remove
	getPage
	count
)

// Store is a instance of a sqlite3 connection and numerous prepared statements
type Store struct {
	db         *sqlite3.Conn
	mutex      sync.Mutex
	statements map[string][]statement
}

// NewStore takes the filename of a new or existing sqlite3 database
func NewStore(filename string) (*Store, error) {
	s, err := sqlite3.Open(filename)
	if err != nil {
		return nil, err
	}
	return &Store{
		db:         s,
		statements: make(map[string][]statement),
	}, nil
}

// Close closes the sqlite3 database
func (s *Store) Close() error {
	return s.db.Close()
}

// Register allows a type to be registered with the store, creating the table if
// it does not already exists and prepares the common statements.
func (s *Store) Register(t Interface) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	table := tableName(t)

	if _, ok := s.statements[table]; ok {
		return nil
	}

	tVars := t.Get()

	var sqlVars, sqlParams, setSQLParams, tableVars string
	vars := make([]string, 0, len(tVars))

	first := true
	oFirst := true
	primary := t.Key()

	for typeName, typeVal := range tVars {
		if first {
			first = false
		} else {
			tableVars += ", "
		}
		if primary != typeName {
			if oFirst {
				oFirst = false
			} else {
				sqlVars += ", "
				setSQLParams += ", "
				sqlParams += ", "
			}
		}
		varType := getType(typeVal)
		tableVars += "[" + typeName + "] " + varType
		if primary == typeName {
			tableVars += " PRIMARY KEY AUTOINCREMENT"
		} else {
			sqlVars += "[" + typeName + "]"
			setSQLParams += "[" + typeName + "] = ?"
			sqlParams += "?"
			vars = append(vars, typeName)
		}
	}
	pVars := append(vars, primary)
	sql := "CREATE TABLE IF NOT EXISTS [" + table + "](" + tableVars + ");"
	err := s.db.Exec(sql)
	if err != nil {
		return err
	}
	s.statements[table] = make([]statement, 6)

	sql = "INSERT INTO [" + table + "] (" + sqlVars + ") VALUES (" + sqlParams + ");"
	stmt, err := s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][add] = statement{Stmt: stmt, vars: vars}

	sql = "SELECT " + sqlVars + " FROM [" + table + "] WHERE [" + primary + "] = ? LIMIT 1;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][get] = statement{Stmt: stmt, vars: vars}

	sql = "UPDATE [" + table + "] SET " + setSQLParams + " WHERE [" + primary + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][update] = statement{Stmt: stmt, vars: pVars}

	sql = "DELETE FROM [" + table + "] WHERE [" + primary + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][remove] = statement{Stmt: stmt}

	sql = "SELECT " + sqlVars + ", [" + primary + "] FROM [" + table + "] ORDER BY [" + primary + "] LIMIT ? OFFSET ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][getPage] = statement{Stmt: stmt, vars: pVars}

	sql = "SELECT COUNT(1) FROM [" + table + "];"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][count] = statement{Stmt: stmt}

	return nil
}

// Set will store the given data into the database. The instances of Interface
// do not need to be of the same type.
func (s *Store) Set(ts ...Interface) (id int, err error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for _, t := range ts {
		table := tableName(t)
		vars := t.Get()
		p := vars[t.Key()]
		var primary int
		if v, ok := p.(*int); ok {
			primary = *v
		} else {
			err = WrongKeyType{}
			return id, err
		}
		if primary == 0 {
			stmt := s.statements[table][add]
			err = stmt.Exec(unPointers(stmt.Vars(vars))...)
			if err != nil {
				return id, err
			}
			id = int(s.db.LastInsertId())
		} else {
			stmt := s.statements[table][update]
			err = stmt.Exec(unPointers(stmt.Vars(vars))...)
			if err != nil {
				return id, err
			}
			id = primary
		}
	}
	return id, err
}

// Get will retrieve the data from the database. The instances of Interface do
// not need to be of the same type.
func (s *Store) Get(data ...Interface) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for _, t := range data {
		table := tableName(t)
		stmt := s.statements[table][get]
		vars := t.Get()
		err := stmt.Query(unPointer(vars[t.Key()]))
		if err != nil && err != io.EOF {
			return err
		}
		err = stmt.Scan(stmt.Vars(vars)...)
		if err == io.EOF {
			if v, ok := vars[t.Key()].(*int); ok {
				*v = 0
			}
		} else if err != nil {
			return err
		}
	}
	return nil
}

// GetPage will get data of a single type from the database. The offset is the
// number of items that is to be skipped before filling the data.
//
// The types of data all need to be of the same concrete type.
//
// Returns the number of items retrieved and an error if any occurred.
func (s *Store) GetPage(data []Interface, offset int) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if len(data) < 1 {
		return 0, nil
	}
	table := tableName(data[0])
	stmt := s.statements[table][getPage]
	var (
		err error
		pos int
	)
	for err = stmt.Query(len(data), offset); err == nil; err = stmt.Next() {
		if typeName := tableName(data[pos]); typeName != table {
			err = UnmatchedType{table, typeName}
		} else {
			err = stmt.Scan(stmt.Vars(data[pos].Get())...)
			pos++
		}
	}
	if err != nil && err != io.EOF {
		return pos, err
	}
	return pos, nil
}

// Delete removes data from the database. The instances of Interface do not
// need to be of the same type.
func (s *Store) Delete(ts ...Interface) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for _, t := range ts {
		table := tableName(t)
		err := s.statements[table][remove].Exec(unPointer(t.Get()[t.Key()]))
		if err != nil {
			return err
		}
	}
	return nil
}

// Count returns the number of entries for the given type
func (s *Store) Count(t Interface) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	table := tableName(t)
	stmt := s.statements[table][count]
	err := stmt.Query()
	if err != nil {
		return 0, err
	}
	num := 0
	err = stmt.Scan(&num)
	if err != nil {
		return 0, err
	}
	return num, nil
}

//Errors

// WrongKeyType is an error given when the primary key is not of type int.
type WrongKeyType struct{}

func (WrongKeyType) Error() string {
	return "primary key needs to be int"
}

// UnmatchedType is an error given when an instance of Interface does not match
// a previous instance.
type UnmatchedType struct {
	MainType, ThisType string
}

func (u UnmatchedType) Error() string {
	return "expecting type " + u.MainType + ", got type " + u.ThisType
}
<commit_msg>Initial changes<commit_after>// Package store uses an Interface to automatically store information in a sqlite database
package store

import (
	"database/sql"
	"errors"
	"io"
	"reflect"
	"sync"

	_ "github.com/mxk/go-sqlite/sqlite3"
)

const (
	add = iota
	get
	update
	remove
	getPage
	count
)

// Store is a instance of a sqlite3 connection and numerous prepared statements
type Store struct {
	db         *sql.DB
	mutex      sync.Mutex
	statements map[string][]statement
	types      map[string]typeInfo
}

// New takes the filename of a new or existing sqlite3 database
func New(driverName, dataSourceName string) (*Store, error) {
	s, err := sql.Open(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}
	return &Store{
		db:         s,
		statements: make(map[string][]statement),
	}, nil
}

type typeInfo struct {
	key    int
	fields []fieldInfo
}

type fieldInfo struct {
	pointer bool
	name    string
	pos     []int
}

// Close closes the sqlite3 database
func (s *Store) Close() error {
	err := s.db.Close()
	s.db = nil
	return err
}

// Register allows a type to be registered with the store, creating the table if
// it does not already exists and prepares the common statements.
func (s *Store) Register(t interface{}) error {
	if s.db == nil {
		return Closed
	}
	p := reflect.ValueOf(t)
	if p.Kind() != reflect.Pointer || p.Elem().Kind() != reflect.Struct {
		return NotPointerStruct
	}

	s.mutex.Lock()
	defer s.mutex.Unlock()

	table := tableName(t)

	if _, ok := s.statements[table]; ok {
		return nil
	}
	s.statements[table] = make([]statement, 6)
	if err := s.parseType(t); err != nil {
		return err
	}
	if err := s.makeStatements(table); err != nil {
		return err
	}
	return nil
}

func (s *Store) parseType(t interface{}) error {
	typ := p.Elem().Type()
	for i := 0; i < typ.NumField(); i++ {
		if f := typ.Field(i); f.PkgPath == "" {
			name := f.Name
			if tag := f.Tag.Get("store"); tag == "-" {
				continue
			} else if tag != "" {
				name = tag
			}
			if q := p.Elem().Field(i); q.Kind() == reflect.Ptr && q.Elem().Kind() == reflect.Struct {
				d := q.Elem().Interface()
				if err := s.Register(d); err != nil {
					return err
				}
				tmp := s.types[tableName(d)]
				tmpVal := tmp.fields[tmp.key]
				pos := make([]int, 1, len(tmpVal.pos)+1)
				pos[0] = i
				pos = append(pos, tmpVal.pos...)
				fieldInfo{
					tmpVal.pointer,
					name,
					pos,
				}
			} else {

			}
		}
	}

	return nil
}

func (s *Store) makeStatements(table string) error {
	typ := s.types[table]
	first := true
	primary := typ.fields[typ.key].name
	oFirst := true

	var tableVars, sqlVars, setSQLParams, sqlParams string

	for n, field := range typ.fields {
		if first {
			first = false
		} else {
			tableVars += ", "
		}
		if typ.key != n {
			if oFirst {
				oFirst = false
			} else {
				sqlVars += ", "
				setSQLParams += ", "
				sqlParams += ", "
			}
		}
		tableVars += "[" + typeName + "] " + varType
		if n == typ.key {
			tableVars += " PRIMARY KEY AUTOINCREMENT"
		} else {
			sqlVars += "[" + typeName + "]"
			setSQLParams += "[" + typeName + "] = ?"
			sqlParams += "?"
		}
	}
	pVars := append(vars, primary)
	sql := "CREATE TABLE IF NOT EXISTS [" + table + "](" + tableVars + ");"
	err := s.db.Exec(sql)
	if err != nil {
		return err
	}

	sql = "INSERT INTO [" + table + "] (" + sqlVars + ") VALUES (" + sqlParams + ");"
	stmt, err := s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][add] = statement{Stmt: stmt, vars: vars}

	sql = "SELECT " + sqlVars + " FROM [" + table + "] WHERE [" + primary + "] = ? LIMIT 1;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][get] = statement{Stmt: stmt, vars: vars}

	sql = "UPDATE [" + table + "] SET " + setSQLParams + " WHERE [" + primary + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][update] = statement{Stmt: stmt, vars: pVars}

	sql = "DELETE FROM [" + table + "] WHERE [" + primary + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][remove] = statement{Stmt: stmt}

	sql = "SELECT " + sqlVars + ", [" + primary + "] FROM [" + table + "] ORDER BY [" + primary + "] LIMIT ? OFFSET ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][getPage] = statement{Stmt: stmt, vars: pVars}

	sql = "SELECT COUNT(1) FROM [" + table + "];"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	s.statements[table][count] = statement{Stmt: stmt}

	return nil
}

// Set will store the given data into the database. The instances of Interface
// do not need to be of the same type.
func (s *Store) Set(ts ...Interface) (id int, err error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for _, t := range ts {
		table := tableName(t)
		vars := t.Get()
		p := vars[t.Key()]
		var primary int
		if v, ok := p.(*int); ok {
			primary = *v
		} else {
			err = WrongKeyType
			return id, err
		}
		if primary == 0 {
			stmt := s.statements[table][add]
			err = stmt.Exec(unPointers(stmt.Vars(vars))...)
			if err != nil {
				return id, err
			}
			id = int(s.db.LastInsertId())
		} else {
			stmt := s.statements[table][update]
			err = stmt.Exec(unPointers(stmt.Vars(vars))...)
			if err != nil {
				return id, err
			}
			id = primary
		}
	}
	return id, err
}

// Get will retrieve the data from the database. The instances of Interface do
// not need to be of the same type.
func (s *Store) Get(data ...Interface) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for _, t := range data {
		table := tableName(t)
		stmt := s.statements[table][get]
		vars := t.Get()
		err := stmt.Query(unPointer(vars[t.Key()]))
		if err != nil && err != io.EOF {
			return err
		}
		err = stmt.Scan(stmt.Vars(vars)...)
		if err == io.EOF {
			if v, ok := vars[t.Key()].(*int); ok {
				*v = 0
			}
		} else if err != nil {
			return err
		}
	}
	return nil
}

// GetPage will get data of a single type from the database. The offset is the
// number of items that is to be skipped before filling the data.
//
// The types of data all need to be of the same concrete type.
//
// Returns the number of items retrieved and an error if any occurred.
func (s *Store) GetPage(data []Interface, offset int) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if len(data) < 1 {
		return 0, nil
	}
	table := tableName(data[0])
	stmt := s.statements[table][getPage]
	var (
		err error
		pos int
	)
	for err = stmt.Query(len(data), offset); err == nil; err = stmt.Next() {
		if typeName := tableName(data[pos]); typeName != table {
			err = UnmatchedType{table, typeName}
		} else {
			err = stmt.Scan(stmt.Vars(data[pos].Get())...)
			pos++
		}
	}
	if err != nil && err != io.EOF {
		return pos, err
	}
	return pos, nil
}

// Delete removes data from the database. The instances of Interface do not
// need to be of the same type.
func (s *Store) Delete(ts ...Interface) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for _, t := range ts {
		table := tableName(t)
		err := s.statements[table][remove].Exec(unPointer(t.Get()[t.Key()]))
		if err != nil {
			return err
		}
	}
	return nil
}

// Count returns the number of entries for the given type
func (s *Store) Count(t Interface) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	table := tableName(t)
	stmt := s.statements[table][count]
	err := stmt.Query()
	if err != nil {
		return 0, err
	}
	num := 0
	err = stmt.Scan(&num)
	if err != nil {
		return 0, err
	}
	return num, nil
}

//Errors

var (
	// Closed is an error given when trying to perform an operation on a
	// closed database connection
	Closed = errors.New("database is closed")

	// WrongKeyType is an error given when the primary key is not of type int.
	WrongKeyType = errors.New("primary key needs to be int")

	// NotStruct is an error given when a Register is given something other
	// than a struct
	NotStruct = errors.New("expecting a struct type")
)

// UnmatchedType is an error given when an instance of Interface does not match
// a previous instance.
type UnmatchedType struct {
	MainType, ThisType string
}

func (u UnmatchedType) Error() string {
	return "expecting type " + u.MainType + ", got type " + u.ThisType
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"fmt"
	// "argon/src/scanner"
)

func main() {
	currentLine  := 0
	currentColl  := 0
	sourceIndex  := 0
	indexing     := false
	indexerStart := 0
	tracker      := 0
	const_string_mode := false;
	cookieJar    := []string{}
	file, err    := ioutil.ReadFile("../testfiles/main.ar")
	lexedToken   := &token{"0",0,0,0,"0"}
	if err != nil {
		panic(err)
	}
	for i := 0; i < len(string(file)); i++ {

		char := GET("../testFiles/main.ar", currentColl, currentLine, sourceIndex);

    lexedToken = lex(char);

		//this handles reading out non-string constants

		if lexedToken.tokenType == "STRING" || lexedToken.tokenType == "STRING_CONSTANT" && !const_string_mode{

			if(!indexing){
				indexerStart = lexedToken.sourceIndex;
			}

			if(lexedToken.tokenType == "STRING_CONSTANT"){
				const_string_mode = true;
				fmt.Println("found a \" ")
			}

			indexing = true;
			tracker++;

		}else if(indexing && const_string_mode){
			tracker++
				if(lexedToken.tokenType == "STRING_CONSTANT"){

					cookieJar = append(cookieJar, concatCookie(StackCookies([]int{indexerStart,tracker,indexerStart+tracker-1,lexedToken.lineIndex})))
					fmt.Println("indexing and const_string_mode and tokenType == STRING_CONSTANT")
					tracker = 0;
					indexerStart = 0;
					indexing = false;
					const_string_mode = false;
				}
	}else if(indexing && !const_string_mode){
		cookieJar = append(cookieJar, concatCookie(StackCookies([]int{indexerStart,tracker,indexerStart+tracker-1,lexedToken.lineIndex})))
		fmt.Println("tracker for append = ", tracker);
		tracker = 0;
		indexerStart = 0;
		indexing = false;
	}

		if char.cargo == "NEWLINE" {
			currentLine += 1
			currentColl = 0
		}

		sourceIndex += 1
		currentColl += 1

		}
		//test. remove once we confirm it works
		for i := 0; i < len(cookieJar); i++ {
			fmt.Println(cookieJar[i])
		}
	}

//this function is for the parser to request tokens from the lexer.
// func eat(tokenList []string, TkIndex int) *token{
//
// }

func lex(char *char) *token {

	//if the char is a letter
  if(isIn(char.cargo, IDENTIFIER_STARTCHARS())){

		return &token{char.cargo,char.sourceIndex,char.lineIndex,char.colIndex,"STRING"}

	}else if(isIn(char.cargo, NUMBER_CHARS())){

		return &token{char.cargo,char.sourceIndex,char.lineIndex,char.colIndex,"INTEGER"}

	}else if(isIn(char.cargo, STRING_CHARACTERS())){

			return &token{char.cargo,char.sourceIndex,char.lineIndex,char.colIndex,"STRING_CONSTANT"}

	}else if(isIn(char.cargo, ONE_CHARACTER_SYMBOLS())){

			return &token{char.cargo,char.sourceIndex,char.lineIndex,char.colIndex,"SYMBOL"}

	}
		return &token{char.cargo,char.sourceIndex,char.lineIndex,char.colIndex,"ERROR"}

}

func isIn(character string, section []string) bool{
  for i := 0; i < len(section); i++ {
    if section[i] == character{
    return true
		}
	}
	return false
}

func StackCookies(r []int) []string{
	cookieStack := []string{}

	for i := 0; i < r[1]; i++ {

		//cookies in the cookieJar are listed as follows : indexerStart /
		//																								 tracker			/
		//																					indexerStart + tracker -1 /
		//																								line 					/
		cookieStack = append(cookieStack, GET("../testfiles/main.ar", r[0]+i, r[3], r[0]+i).cargo);
				fmt.Println("adding : ", GET("../testfiles/main.ar", r[0]+i, r[3], r[0]+i).cargo, "to stack. stack is now" , cookieStack);
	}
	fmt.Println("SC output : " , cookieStack);
	return cookieStack;
}

//function to hang a type to concatenated or constant strings;
// func validate(toValidate string) {
//
// }

//function for concatinating cookies
func concatCookie(r []string) string {
	f := "";
	for i := 0; i < len(r); i++ {
		f += r[i];
	}
	// fmt.Println("outputted : ", f );
	return f;
}
<commit_msg>added code commenting for the lexer<commit_after>package main

import (
	"io/ioutil"
	"fmt"
	// "argon/src/scanner"
)

func main() {
	currentLine  := 0
	currentColl  := 0
	sourceIndex  := 0
	indexing     := false
	indexerStart := 0
	tracker      := 0
	const_string_mode := false;
	cookieJar    := []string{}
	file, err    := ioutil.ReadFile("../testfiles/main.ar")
	lexedToken   := &token{"0",0,0,0,"0"}
	if err != nil {
		panic(err)
	}
	for i := 0; i < len(string(file)); i++ {

		char := GET("../testFiles/main.ar", currentColl, currentLine, sourceIndex);

    lexedToken = lex(char);

		//this handles reading out non-string constants

		// if its a string or litteral string token and its not tracking a litteral string
		if lexedToken.tokenType == "STRING" || lexedToken.tokenType == "STRING_CONSTANT" && !const_string_mode{
			//if its not tracking
			if(!indexing){
				indexerStart = lexedToken.sourceIndex;
			}
			// if its a litteral string token
			if(lexedToken.tokenType == "STRING_CONSTANT"){
				const_string_mode = true;
				fmt.Println("found a \" ")
			}

			indexing = true;
			tracker++;
			//if tracking a litteral string
		}else if(indexing && const_string_mode){

			tracker++
				//if it finds a litteral string token while already lexing a litteral string
				if(lexedToken.tokenType == "STRING_CONSTANT"){

					cookieJar = append(cookieJar, concatCookie(StackCookies([]int{indexerStart,tracker,indexerStart+tracker-1,lexedToken.lineIndex})))
					fmt.Println("indexing and const_string_mode and tokenType == STRING_CONSTANT")
					tracker = 0;
					indexerStart = 0;
					indexing = false;
					const_string_mode = false;

				}
	//if its tracking but not tracking a litteral string
	}else if(indexing && !const_string_mode){

		cookieJar = append(cookieJar, concatCookie(StackCookies([]int{indexerStart,tracker,indexerStart+tracker-1,lexedToken.lineIndex})))
		fmt.Println("tracker for append = ", tracker);
		tracker = 0;
		indexerStart = 0;
		indexing = false;

	}

		if char.cargo == "NEWLINE" {
			currentLine += 1
			currentColl = 0
		}

		sourceIndex += 1
		currentColl += 1

		}
		//test. remove once we confirm it works
		for i := 0; i < len(cookieJar); i++ {
			fmt.Println(cookieJar[i])
		}
	}

//this function is for the parser to request tokens from the lexer.
// func eat(tokenList []string, TkIndex int) *token{
//
// }

func lex(char *char) *token {

	//if the char is a letter
  if(isIn(char.cargo, IDENTIFIER_STARTCHARS())){

		return &token{char.cargo,char.sourceIndex,char.lineIndex,char.colIndex,"STRING"}

	}else if(isIn(char.cargo, NUMBER_CHARS())){

		return &token{char.cargo,char.sourceIndex,char.lineIndex,char.colIndex,"INTEGER"}

	}else if(isIn(char.cargo, STRING_CHARACTERS())){

			return &token{char.cargo,char.sourceIndex,char.lineIndex,char.colIndex,"STRING_CONSTANT"}

	}else if(isIn(char.cargo, ONE_CHARACTER_SYMBOLS())){

			return &token{char.cargo,char.sourceIndex,char.lineIndex,char.colIndex,"SYMBOL"}

	}
		return &token{char.cargo,char.sourceIndex,char.lineIndex,char.colIndex,"ERROR"}

}

func isIn(character string, section []string) bool{
  for i := 0; i < len(section); i++ {
    if section[i] == character{
    return true
		}
	}
	return false
}

func StackCookies(r []int) []string{
	cookieStack := []string{}

	for i := 0; i < r[1]; i++ {

		//cookies in the cookieJar are listed as follows : indexerStart /
		//																								 tracker			/
		//																					indexerStart + tracker -1 /
		//																								line 					/
		cookieStack = append(cookieStack, GET("../testfiles/main.ar", r[0]+i, r[3], r[0]+i).cargo);
				fmt.Println("adding : ", GET("../testfiles/main.ar", r[0]+i, r[3], r[0]+i).cargo, "to stack. stack is now" , cookieStack);
	}
	fmt.Println("SC output : " , cookieStack);
	return cookieStack;
}

//function to hang a type to concatenated or constant strings;
// func validate(toValidate string) {
//
// }

//function for concatinating cookies
func concatCookie(r []string) string {
	f := "";
	for i := 0; i < len(r); i++ {
		f += r[i];
	}
	// fmt.Println("outputted : ", f );
	return f;
}
<|endoftext|>


<commit_before>package sweet

import (
	"fmt"
	"path"
	"reflect"
	"strings"
	"sync"
	"testing"
	"time"
)

type suiteRunner struct {
	s     *S
	suite interface{}

	suppressDeprecation bool
	deprecatedUsages    []string
}

func newSuiteRunner(s *S, suite interface{}) *suiteRunner {
	return &suiteRunner{
		s:                s,
		suite:            suite,
		deprecatedUsages: make([]string, 0),
	}
}

func (s *suiteRunner) addDeprecationWarning(funcName string) {
	s.deprecatedUsages = append(s.deprecatedUsages, funcName)
}

func (s *suiteRunner) runPlugins(f func(plugin Plugin)) {
	for _, plugin := range s.s.plugins {
		f(plugin)
	}
}

func (s *suiteRunner) Run(t *testing.T) {
	suiteStart := time.Now()

	var testGroup sync.WaitGroup

	suiteVal := reflect.ValueOf(s.suite)
	suiteType := suiteVal.Type()

	suiteName := suiteType.Name()
	if suiteVal.CanInterface() {
		suiteIfaceVal := reflect.Indirect(suiteVal)
		if suiteIfaceVal == reflect.Zero(suiteType) {
			suiteName = "UnknownSuite"
		} else {
			suiteName = suiteIfaceVal.Type().Name()
		}
	}

	lowerName := strings.ToLower(suiteName)
	if len(flagInclude) > 0 {
		found := false
		for _, name := range flagInclude {
			if strings.ToLower(name) == lowerName {
				found = true
				break
			}
		}
		if !found {
			return
		}
	}
	if len(flagExclude) > 0 {
		for _, name := range flagExclude {
			if strings.ToLower(name) == lowerName {
				return
			}
		}
	}

	setUpSuiteVal := suiteVal.MethodByName(defSetUpSuite.Name)
	tearDownSuiteVal := suiteVal.MethodByName(defTearDownSuite.Name)

	setUpTestVal := suiteVal.MethodByName(defSetUpTest.Name)
	tearDownTestVal := suiteVal.MethodByName(defTearDownTest.Name)

	v, err := defSetUpSuite.Validate(setUpSuiteVal)
	if err == errDeprecated {
		if !s.suppressDeprecation {
			s.addDeprecationWarning(formatName(suiteName, defSetUpSuite.Name))
		}

		// We handled the error, clear it so the set up still runs
		err = nil
	} else if err == errInvalidValue {
		// Skip running the suite set up because it doesn't exist.
	} else if err != nil {
		panic(fmt.Sprintf("%s has an unsupported method signature",
			formatName(suiteName, defSetUpSuite.Name)))
	}
	if err == nil {
		switch v {
		case 1:
			setUpSuiteVal.Call(nil)
		}
	}

	s.runPlugins(func(plugin Plugin) {
		plugin.SuiteStarting(suiteName)
	})
	for idx := 0; idx < suiteVal.NumMethod(); idx++ {
		methodType := suiteType.Method(idx)

		if methodType.Name[:4] == "Test" {
			methodVal := suiteVal.Method(idx)
			testName := methodType.Name
			testFullName := formatName(suiteName, methodType.Name)
			testStart := time.Now()
			t.Run(testFullName, func(t *testing.T) {
				wrapT := newSweetT(t)

				tVal := reflect.ValueOf(t)
				wrapTVal := reflect.ValueOf(wrapT)

				if setUpAllTests != nil {
					setUpAllTests(t)
				}

				v, err := defSetUpTest.Validate(setUpTestVal)
				if err == errDeprecated {
					if !s.suppressDeprecation {
						s.addDeprecationWarning(formatName(suiteName, defSetUpTest.Name))
					}

					// Clean out the error because we've handled it
					err = nil
				} else if err == errInvalidValue {
					// Continue on because a test set up wasn't provided.
				} else if err != nil {
					panic(fmt.Sprintf("%s has an unsupported method signature",
						formatName(suiteName, defSetUpTest.Name)))
				}
				if err == nil {
					switch v {
					case 1:
						setUpTestVal.Call([]reflect.Value{tVal})
					case 2:
						setUpTestVal.Call([]reflect.Value{wrapTVal})
					}
				}

				// Call the actual test function in something that we can recover from
				failureStats := &TestFailedStats{
					Name:   testFullName,
					Frames: make([]*TestFailedFrame, 0),
				}
				func() {
					defer func() {
						if r := recover(); r != nil {
							switch result := r.(type) {
							case *testFailed:
								failureStats.Message = result.Message
								failureStats.Frames = make(
									[]*TestFailedFrame,
									len(result.Frames),
								)
								frameCount := len(result.Frames) - 1
								for idx := frameCount; idx >= 0; idx-- {
									frame := result.Frames[idx]
									failureStats.Frames[frameCount-idx] = &TestFailedFrame{
										File: frame.Filename,
										Line: frame.LineNumber,
									}
								}
							case *testSkipped:
								fmt.Printf("test skipped\n")
							default:
								panic(r)
							}
						}

						testGroup.Done()
					}()

					testGroup.Add(1)
					s.runPlugins(func(plugin Plugin) {
						plugin.TestStarting(suiteName, testName)
					})

					v, err := defTest.Validate(methodVal)
					if err == errDeprecated {
						if !s.suppressDeprecation {
							s.addDeprecationWarning(formatName(suiteName, testName))
						}

						// We handled the error, clear it so the test still runs
						err = nil
					} else if err == errInvalidValue {
						panic("There's a test we can't get info for, context the Sweet dev!\n")
					} else if err != nil {
						panic(fmt.Sprintf("%s has an unsupported method signature.",
							formatName(suiteName, testName)))
					}
					if err == nil {
						switch v {
						case 1:
							methodVal.Call([]reflect.Value{tVal})
						case 2:
							methodVal.Call([]reflect.Value{wrapTVal})
						}
					}
				}()

				v, err = defTearDownTest.Validate(tearDownTestVal)
				if err == errDeprecated {
					if !s.suppressDeprecation {
						s.addDeprecationWarning(formatName(suiteName, defTearDownTest.Name))
					}

					// We handled the error, clear it so the clean up still runs
					err = nil
				} else if err == errInvalidValue {
					// Continue on because a test tear down was not provided
				} else if err != nil {
					panic(fmt.Sprintf("%s has an unsupported method signature",
						formatName(suiteName, defTearDownTest.Name)))
				}
				if err == nil {
					switch v {
					case 1:
						tearDownTestVal.Call([]reflect.Value{tVal})
					}
				}

				if tearDownAllTests != nil {
					tearDownAllTests(t)
				}

				s.runPlugins(func(plugin Plugin) {
					if wrapT.Failed() {
						plugin.TestFailed(suiteName, testName, failureStats)
					} else if wrapT.Skipped() {
						plugin.TestSkipped(suiteName, testName, &TestSkippedStats{
							Time: time.Since(testStart),
						})
					} else {
						plugin.TestPassed(suiteName, testName, &TestPassedStats{
							Time: time.Since(testStart),
						})
					}
				})

				if wrapT.Failed() {
					fmt.Printf("-------------------------------------------------\n")
					fmt.Printf("FAIL: %s\n\n", failureStats.Name)

					for _, line := range wrapT.output {
						fmt.Print(line)
					}
					if len(wrapT.output) > 0 {
						fmt.Printf("\n")
					}

					for _, frame := range failureStats.Frames {
						fmt.Printf("%s:%d\n", path.Base(frame.File), frame.Line)
					}

					fmt.Printf("%s\n\n", failureStats.Message)
				}
			})
		}
	}

	v, err = defTearDownSuite.Validate(tearDownSuiteVal)
	if err == errDeprecated {
		if !s.suppressDeprecation {
			s.addDeprecationWarning(formatName(suiteName, defTearDownSuite.Name))
		}

		// We handled the error, clear it so the tear down is still run
		err = nil
	} else if err == errInvalidValue {
		// Continue on because a suite tear down was not provided.
	} else if err != nil {
		panic(fmt.Sprintf("%s has an unsupported method signature",
			formatName(suiteName, defTearDownSuite.Name)))
	}
	if err == nil {
		switch v {
		case 1:
			tearDownSuiteVal.Call(nil)
		}
	}

	testGroup.Wait()

	s.runPlugins(func(plugin Plugin) {
		plugin.SuiteFinished(suiteName, &SuiteFinishedStats{
			Time: time.Since(suiteStart),
		})
	})
}
<commit_msg>Add an additional blank line after output from a test<commit_after>package sweet

import (
	"fmt"
	"path"
	"reflect"
	"strings"
	"sync"
	"testing"
	"time"
)

type suiteRunner struct {
	s     *S
	suite interface{}

	suppressDeprecation bool
	deprecatedUsages    []string
}

func newSuiteRunner(s *S, suite interface{}) *suiteRunner {
	return &suiteRunner{
		s:                s,
		suite:            suite,
		deprecatedUsages: make([]string, 0),
	}
}

func (s *suiteRunner) addDeprecationWarning(funcName string) {
	s.deprecatedUsages = append(s.deprecatedUsages, funcName)
}

func (s *suiteRunner) runPlugins(f func(plugin Plugin)) {
	for _, plugin := range s.s.plugins {
		f(plugin)
	}
}

func (s *suiteRunner) Run(t *testing.T) {
	suiteStart := time.Now()

	var testGroup sync.WaitGroup

	suiteVal := reflect.ValueOf(s.suite)
	suiteType := suiteVal.Type()

	suiteName := suiteType.Name()
	if suiteVal.CanInterface() {
		suiteIfaceVal := reflect.Indirect(suiteVal)
		if suiteIfaceVal == reflect.Zero(suiteType) {
			suiteName = "UnknownSuite"
		} else {
			suiteName = suiteIfaceVal.Type().Name()
		}
	}

	lowerName := strings.ToLower(suiteName)
	if len(flagInclude) > 0 {
		found := false
		for _, name := range flagInclude {
			if strings.ToLower(name) == lowerName {
				found = true
				break
			}
		}
		if !found {
			return
		}
	}
	if len(flagExclude) > 0 {
		for _, name := range flagExclude {
			if strings.ToLower(name) == lowerName {
				return
			}
		}
	}

	setUpSuiteVal := suiteVal.MethodByName(defSetUpSuite.Name)
	tearDownSuiteVal := suiteVal.MethodByName(defTearDownSuite.Name)

	setUpTestVal := suiteVal.MethodByName(defSetUpTest.Name)
	tearDownTestVal := suiteVal.MethodByName(defTearDownTest.Name)

	v, err := defSetUpSuite.Validate(setUpSuiteVal)
	if err == errDeprecated {
		if !s.suppressDeprecation {
			s.addDeprecationWarning(formatName(suiteName, defSetUpSuite.Name))
		}

		// We handled the error, clear it so the set up still runs
		err = nil
	} else if err == errInvalidValue {
		// Skip running the suite set up because it doesn't exist.
	} else if err != nil {
		panic(fmt.Sprintf("%s has an unsupported method signature",
			formatName(suiteName, defSetUpSuite.Name)))
	}
	if err == nil {
		switch v {
		case 1:
			setUpSuiteVal.Call(nil)
		}
	}

	s.runPlugins(func(plugin Plugin) {
		plugin.SuiteStarting(suiteName)
	})
	for idx := 0; idx < suiteVal.NumMethod(); idx++ {
		methodType := suiteType.Method(idx)

		if methodType.Name[:4] == "Test" {
			methodVal := suiteVal.Method(idx)
			testName := methodType.Name
			testFullName := formatName(suiteName, methodType.Name)
			testStart := time.Now()
			t.Run(testFullName, func(t *testing.T) {
				wrapT := newSweetT(t)

				tVal := reflect.ValueOf(t)
				wrapTVal := reflect.ValueOf(wrapT)

				if setUpAllTests != nil {
					setUpAllTests(t)
				}

				v, err := defSetUpTest.Validate(setUpTestVal)
				if err == errDeprecated {
					if !s.suppressDeprecation {
						s.addDeprecationWarning(formatName(suiteName, defSetUpTest.Name))
					}

					// Clean out the error because we've handled it
					err = nil
				} else if err == errInvalidValue {
					// Continue on because a test set up wasn't provided.
				} else if err != nil {
					panic(fmt.Sprintf("%s has an unsupported method signature",
						formatName(suiteName, defSetUpTest.Name)))
				}
				if err == nil {
					switch v {
					case 1:
						setUpTestVal.Call([]reflect.Value{tVal})
					case 2:
						setUpTestVal.Call([]reflect.Value{wrapTVal})
					}
				}

				// Call the actual test function in something that we can recover from
				failureStats := &TestFailedStats{
					Name:   testFullName,
					Frames: make([]*TestFailedFrame, 0),
				}
				func() {
					defer func() {
						if r := recover(); r != nil {
							switch result := r.(type) {
							case *testFailed:
								failureStats.Message = result.Message
								failureStats.Frames = make(
									[]*TestFailedFrame,
									len(result.Frames),
								)
								frameCount := len(result.Frames) - 1
								for idx := frameCount; idx >= 0; idx-- {
									frame := result.Frames[idx]
									failureStats.Frames[frameCount-idx] = &TestFailedFrame{
										File: frame.Filename,
										Line: frame.LineNumber,
									}
								}
							case *testSkipped:
								fmt.Printf("test skipped\n")
							default:
								panic(r)
							}
						}

						testGroup.Done()
					}()

					testGroup.Add(1)
					s.runPlugins(func(plugin Plugin) {
						plugin.TestStarting(suiteName, testName)
					})

					v, err := defTest.Validate(methodVal)
					if err == errDeprecated {
						if !s.suppressDeprecation {
							s.addDeprecationWarning(formatName(suiteName, testName))
						}

						// We handled the error, clear it so the test still runs
						err = nil
					} else if err == errInvalidValue {
						panic("There's a test we can't get info for, context the Sweet dev!\n")
					} else if err != nil {
						panic(fmt.Sprintf("%s has an unsupported method signature.",
							formatName(suiteName, testName)))
					}
					if err == nil {
						switch v {
						case 1:
							methodVal.Call([]reflect.Value{tVal})
						case 2:
							methodVal.Call([]reflect.Value{wrapTVal})
						}
					}
				}()

				v, err = defTearDownTest.Validate(tearDownTestVal)
				if err == errDeprecated {
					if !s.suppressDeprecation {
						s.addDeprecationWarning(formatName(suiteName, defTearDownTest.Name))
					}

					// We handled the error, clear it so the clean up still runs
					err = nil
				} else if err == errInvalidValue {
					// Continue on because a test tear down was not provided
				} else if err != nil {
					panic(fmt.Sprintf("%s has an unsupported method signature",
						formatName(suiteName, defTearDownTest.Name)))
				}
				if err == nil {
					switch v {
					case 1:
						tearDownTestVal.Call([]reflect.Value{tVal})
					}
				}

				if tearDownAllTests != nil {
					tearDownAllTests(t)
				}

				s.runPlugins(func(plugin Plugin) {
					if wrapT.Failed() {
						plugin.TestFailed(suiteName, testName, failureStats)
					} else if wrapT.Skipped() {
						plugin.TestSkipped(suiteName, testName, &TestSkippedStats{
							Time: time.Since(testStart),
						})
					} else {
						plugin.TestPassed(suiteName, testName, &TestPassedStats{
							Time: time.Since(testStart),
						})
					}
				})

				if wrapT.Failed() {
					fmt.Printf("-------------------------------------------------\n")
					fmt.Printf("FAIL: %s\n\n", failureStats.Name)

					for _, line := range wrapT.output {
						fmt.Print(line)
					}
					if len(wrapT.output) > 0 {
						fmt.Printf("\n\n")
					}

					for _, frame := range failureStats.Frames {
						fmt.Printf("%s:%d\n", path.Base(frame.File), frame.Line)
					}

					fmt.Printf("%s\n\n", failureStats.Message)
				}
			})
		}
	}

	v, err = defTearDownSuite.Validate(tearDownSuiteVal)
	if err == errDeprecated {
		if !s.suppressDeprecation {
			s.addDeprecationWarning(formatName(suiteName, defTearDownSuite.Name))
		}

		// We handled the error, clear it so the tear down is still run
		err = nil
	} else if err == errInvalidValue {
		// Continue on because a suite tear down was not provided.
	} else if err != nil {
		panic(fmt.Sprintf("%s has an unsupported method signature",
			formatName(suiteName, defTearDownSuite.Name)))
	}
	if err == nil {
		switch v {
		case 1:
			tearDownSuiteVal.Call(nil)
		}
	}

	testGroup.Wait()

	s.runPlugins(func(plugin Plugin) {
		plugin.SuiteFinished(suiteName, &SuiteFinishedStats{
			Time: time.Since(suiteStart),
		})
	})
}
<|endoftext|>


<commit_before>/*package catalog contains funcitons for reading from and writing to
files containing catalogs of particle locations and velocities.

Catalogs written by external programs are standardized to a single type when
read. Currently the only such extrenal catalog type that is supported the
Gadget 2 particle catalog.

The binary format used is as follows:
    |-- 1 --||-- 2 --||-- 3 --||-- ... 4 ... --||-- ... 5 ... --|

    1 - (int32) Flag indicating the endianness of the file. 0 indicates a big
        endian byte ordering and -1 indicates a little endian byte order.
    2 - (int32) Size of a Header struct. Should be checked for consistency.
    3 - (int32) Size of a Particle struct. Should be checked for consistency.
    4 - (tetra.Header) Header file containing meta-information about the
        particle catalog.
    5 - ([]tetra.Particle) Contiguous block of particles. Garuanteed to be
        of size unsafe.Sizeof(Particle{}) * header.Count.
*/
package catalog

import (
	"encoding/binary"
	"fmt"
	"io"
	"math"
	"os"

	"unsafe"

	tetra "github.com/phil-mansfield/gotetra"
)

const (
	// Endianness used by default when writing catalogs. Catalogs of any
	// endianness can be read.
	DefaultEndiannessFlag int32 = -1
)

// gadgetHeader is the formatting for meta-information used by Gadget 2.
type gadgetHeader struct {
	NPart                                     [6]uint32
	Mass                                      [6]float64
	Time, Redshift                            float64
	FlagSfr, FlagFeedback                     int32
	NPartTotal                                [6]uint32
	FlagCooling, NumFiles                     int32
	BoxSize, Omega0, OmegaLambda, HubbleParam float64
	FlagStellarAge, HashTabSize               int32

	Padding [88]byte
}

// readInt32 returns single 32-bit interger from the given file using the
// given endianness.
func readInt32(r io.Reader, order binary.ByteOrder) int32 {
	var n int32
	if err := binary.Read(r, order, &n); err != nil {
		panic(err)
	}
	return n
}

// Standardize returns a tetra.Header that corresponds to the source
// Gadget 2 header.
func (gh *gadgetHeader) Standardize() *tetra.Header {
	h := &tetra.Header{}

	h.Count = int64(gh.NPart[1] + gh.NPart[0]<<32)
	h.TotalCount = int64(gh.NPartTotal[1] + gh.NPartTotal[0]<<32)
	h.Mass = float64(gh.Mass[1])
	h.TotalWidth = float64(gh.BoxSize)
	h.Width = -1.0

	h.Cosmo.Z = gh.Redshift
	h.Cosmo.OmegaM = gh.Omega0
	h.Cosmo.OmegaL = gh.OmegaLambda
	h.Cosmo.H100 = gh.HubbleParam

	return h
}

// WrapDistance takes a value and interprets it as a position defined within
// a periodic domain of width h.BoxSize.
func (h *gadgetHeader) WrapDistance(x float64) float64 {
	if x < 0 {
		return x + h.BoxSize
	} else if x >= h.BoxSize {
		return x - h.BoxSize
	}
	return x
}

func ReadGadgetHeader(path string, order binary.ByteOrder) *tetra.Header {
	f, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	gh := &gadgetHeader{}

	_ = readInt32(f, order)
	binary.Read(f, binary.LittleEndian, gh)
	h := gh.Standardize()

	return h
}

func ReadGadgetParticlesAt(
	path string,
	order binary.ByteOrder,
	floatBuf []float32,
	intBuf []int64,
	ps []tetra.Particle,
) {
	f, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	gh := &gadgetHeader{}

	_ = readInt32(f, order)
	binary.Read(f, binary.LittleEndian, gh)
	_ = readInt32(f, order)

	h := gh.Standardize()

	if int64(len(floatBuf)) != 3*h.Count {
		panic("Incorrect length for float buffer.")
	} else if int64(len(intBuf)) != h.Count {
		panic("Incorrect length for int buffer.")
	} else if int64(len(ps)) != h.Count {
		panic("Incorrect length for particle slice.")
	}

	_ = readInt32(f, order)
	binary.Read(f, order, floatBuf)
	_ = readInt32(f, order)

	for i := range ps {
		ps[i].Xs[0] = gh.WrapDistance(float64(floatBuf[3*i+0]))
		ps[i].Xs[1] = gh.WrapDistance(float64(floatBuf[3*i+1]))
		ps[i].Xs[2] = gh.WrapDistance(float64(floatBuf[3*i+2]))
	}

	_ = readInt32(f, order)
	binary.Read(f, order, floatBuf)
	_ = readInt32(f, order)

	rootA := float32(math.Sqrt(float64(gh.Time)))
	for i := range ps {
		ps[i].Vs[0] = float64(floatBuf[3*i+0] * rootA)
		ps[i].Vs[1] = float64(floatBuf[3*i+1] * rootA)
		ps[i].Vs[2] = float64(floatBuf[3*i+2] * rootA)
	}

	_ = readInt32(f, order)
	binary.Read(f, order, intBuf)
	_ = readInt32(f, order)

	for i := range ps {
		ps[i].Id = intBuf[i]
	}
}

// ReadGadget reads the gadget particle catalog located at the given location
// and written with the given endianness. Its header and particle sequence
// are returned in a standardized format.
func ReadGadget(path string, order binary.ByteOrder) (*tetra.Header, []tetra.Particle) {
	f, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	gh := &gadgetHeader{}

	_ = readInt32(f, order)
	binary.Read(f, binary.LittleEndian, gh)
	_ = readInt32(f, order)

	h := gh.Standardize()
	floatBuf := make([]float32, 3*h.Count)
	ps := make([]tetra.Particle, h.Count)

	_ = readInt32(f, order)
	binary.Read(f, order, floatBuf)
	_ = readInt32(f, order)

	for i := range ps {
		ps[i].Xs[0] = gh.WrapDistance(float64(floatBuf[3*i+0]))
		ps[i].Xs[1] = gh.WrapDistance(float64(floatBuf[3*i+1]))
		ps[i].Xs[2] = gh.WrapDistance(float64(floatBuf[3*i+2]))
	}

	_ = readInt32(f, order)
	binary.Read(f, order, floatBuf)
	_ = readInt32(f, order)

	rootA := float32(math.Sqrt(float64(gh.Time)))
	for i := range ps {
		ps[i].Vs[0] = float64(floatBuf[3*i+0] * rootA)
		ps[i].Vs[1] = float64(floatBuf[3*i+1] * rootA)
		ps[i].Vs[2] = float64(floatBuf[3*i+2] * rootA)
	}

	ids := make([]int64, h.Count)

	_ = readInt32(f, order)
	binary.Read(f, order, ids)
	_ = readInt32(f, order)

	for i := range ps {
		ps[i].Id = ids[i]
	}

	return h, ps
}

// Write writes the given header and particle sequence to the specified file.
func Write(path string, h *tetra.Header, ps []tetra.Particle) {
	f, err := os.Create(path)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	h.Count = int64(len(ps))
	order := endianness(DefaultEndiannessFlag)

	err = binary.Write(f, order, DefaultEndiannessFlag)
	if err != nil {
		panic(err.Error())
	}
	err = binary.Write(f, order, int32(unsafe.Sizeof(tetra.Header{})))
	if err != nil {
		panic(err.Error())
	}
	err = binary.Write(f, order, int32(unsafe.Sizeof(ps[0])))
	if err != nil {
		panic(err.Error())
	}
	err = binary.Write(f, order, h)
	if err != nil {
		panic(err.Error())
	}
	err = binary.Write(f, order, ps)
	if err != nil {
		panic(err.Error())
	}
}

// readHeader reads only the header from the given file.
func readHeader(path string) (*tetra.Header, *os.File, binary.ByteOrder) {
	f, err := os.OpenFile(path, os.O_RDWR, os.ModePerm)
	if err != nil {
		panic(err)
	}

	order := endianness(readInt32(f, binary.LittleEndian))

	// Sanity checks:
	headerSize := readInt32(f, order)
	particleSize := readInt32(f, order)
	if int32(unsafe.Sizeof(tetra.Header{})) != headerSize {
		panic(fmt.Sprintf(
			"Size of header in code, %d, does not match size in catalog, %d.",
			unsafe.Sizeof(tetra.Header{}), headerSize,
		))
	} else if int32(unsafe.Sizeof(tetra.Particle{})) != particleSize {
		panic(fmt.Sprintf(
			"Size of header in code, %d, does not match size in catalog, %d.",
			unsafe.Sizeof(tetra.Particle{}), particleSize,
		))
	}

	h := &tetra.Header{}
	err = binary.Read(f, order, h)
	if err != nil {
		panic(err.Error())
	}

	return h, f, order
}

// Append appends a particle sequence to the end of the given file.
func Append(path string, ps []tetra.Particle) {
	if len(ps) == 0 {
		return
	}

	h, f, order := readHeader(path)
	defer f.Close()

	_, err := f.Seek(0, 2)
	if err != nil {
		panic(err.Error())
	}
	err = binary.Write(f, order, ps)
	if err != nil {
		panic(err.Error())
	}

	_, err = f.Seek(12, 0)
	if err != nil {
		panic(err.Error())
	}
	h.Count += int64(len(ps))
	err = binary.Write(f, order, h)
	if err != nil {
		panic(err.Error())
	}
}

// Read reads a header and particle sequence from the given file.
func ReadParticlesAt(path string, ps []tetra.Particle) {
	h, f, order := readHeader(path)
	defer f.Close()

	if int64(len(ps)) != h.Count {
		panic("Incorrect Particle buffer length.")
	}

	err := binary.Read(f, order, ps)
	if err != nil {
		panic(err.Error())
	}
}

// endianness is a utility function converting an endianness flag to a
// byte order.
func endianness(flag int32) binary.ByteOrder {
	if flag == 0 {
		return binary.LittleEndian
	} else if flag == -1 {
		return binary.BigEndian
	} else {
		panic("Unrecognized endianness flag.")
	}
}
<commit_msg>expanded catalog interface and made error messages more descriptive.<commit_after>/*package catalog contains funcitons for reading from and writing to
files containing catalogs of particle locations and velocities.

Catalogs written by external programs are standardized to a single type when
read. Currently the only such extrenal catalog type that is supported the
Gadget 2 particle catalog.

The binary format used is as follows:
    |-- 1 --||-- 2 --||-- 3 --||-- ... 4 ... --||-- ... 5 ... --|

    1 - (int32) Flag indicating the endianness of the file. 0 indicates a big
        endian byte ordering and -1 indicates a little endian byte order.
    2 - (int32) Size of a Header struct. Should be checked for consistency.
    3 - (int32) Size of a Particle struct. Should be checked for consistency.
    4 - (tetra.Header) Header file containing meta-information about the
        particle catalog.
    5 - ([]tetra.Particle) Contiguous block of particles. Garuanteed to be
        of size unsafe.Sizeof(Particle{}) * header.Count.
*/
package catalog

import (
	"encoding/binary"
	"fmt"
	"io"
	"math"
	"os"

	"unsafe"

	tetra "github.com/phil-mansfield/gotetra"
)

const (
	// Endianness used by default when writing catalogs. Catalogs of any
	// endianness can be read.
	DefaultEndiannessFlag int32 = -1
)

// gadgetHeader is the formatting for meta-information used by Gadget 2.
type gadgetHeader struct {
	NPart                                     [6]uint32
	Mass                                      [6]float64
	Time, Redshift                            float64
	FlagSfr, FlagFeedback                     int32
	NPartTotal                                [6]uint32
	FlagCooling, NumFiles                     int32
	BoxSize, Omega0, OmegaLambda, HubbleParam float64
	FlagStellarAge, HashTabSize               int32

	Padding [88]byte
}

// readInt32 returns single 32-bit interger from the given file using the
// given endianness.
func readInt32(r io.Reader, order binary.ByteOrder) int32 {
	var n int32
	if err := binary.Read(r, order, &n); err != nil {
		panic(err)
	}
	return n
}

// Standardize returns a tetra.Header that corresponds to the source
// Gadget 2 header.
func (gh *gadgetHeader) Standardize() *tetra.Header {
	h := &tetra.Header{}

	h.Count = int64(gh.NPart[1] + gh.NPart[0]<<32)
	h.TotalCount = int64(gh.NPartTotal[1] + gh.NPartTotal[0]<<32)
	h.Mass = float64(gh.Mass[1])
	h.TotalWidth = float64(gh.BoxSize)
	h.Width = -1.0

	h.Cosmo.Z = gh.Redshift
	h.Cosmo.OmegaM = gh.Omega0
	h.Cosmo.OmegaL = gh.OmegaLambda
	h.Cosmo.H100 = gh.HubbleParam

	return h
}

// WrapDistance takes a value and interprets it as a position defined within
// a periodic domain of width h.BoxSize.
func (h *gadgetHeader) WrapDistance(x float64) float64 {
	if x < 0 {
		return x + h.BoxSize
	} else if x >= h.BoxSize {
		return x - h.BoxSize
	}
	return x
}

func ReadGadgetHeader(path string, order binary.ByteOrder) *tetra.Header {
	f, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	gh := &gadgetHeader{}

	_ = readInt32(f, order)
	binary.Read(f, binary.LittleEndian, gh)
	h := gh.Standardize()

	return h
}

func ReadGadgetParticlesAt(
	path string,
	order binary.ByteOrder,
	floatBuf []float32,
	intBuf []int64,
	ps []tetra.Particle,
) {
	f, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	gh := &gadgetHeader{}

	_ = readInt32(f, order)
	binary.Read(f, binary.LittleEndian, gh)
	_ = readInt32(f, order)

	h := gh.Standardize()

	if int64(len(floatBuf)) != 3*h.Count {
		panic(fmt.Sprintf(
			"Incorrect length for float buffer. Found %d, expected %d",
			len(floatBuf), 3*h.Count,
		))
	} else if int64(len(intBuf)) != h.Count {
		panic(fmt.Sprintf(
			"Incorrect length for int buffer. Found %d, expected %d",
			len(intBuf), h.Count,
		))
	} else if int64(len(ps)) != h.Count {
		panic(fmt.Sprintf(
			"Incorrect length for Particle buffer. Found %d, expected %d",
			len(ps), h.Count,
		))
	}

	_ = readInt32(f, order)
	binary.Read(f, order, floatBuf)
	_ = readInt32(f, order)

	for i := range ps {
		ps[i].Xs[0] = gh.WrapDistance(float64(floatBuf[3*i+0]))
		ps[i].Xs[1] = gh.WrapDistance(float64(floatBuf[3*i+1]))
		ps[i].Xs[2] = gh.WrapDistance(float64(floatBuf[3*i+2]))
	}

	_ = readInt32(f, order)
	binary.Read(f, order, floatBuf)
	_ = readInt32(f, order)

	rootA := float32(math.Sqrt(float64(gh.Time)))
	for i := range ps {
		ps[i].Vs[0] = float64(floatBuf[3*i+0] * rootA)
		ps[i].Vs[1] = float64(floatBuf[3*i+1] * rootA)
		ps[i].Vs[2] = float64(floatBuf[3*i+2] * rootA)
	}

	_ = readInt32(f, order)
	binary.Read(f, order, intBuf)
	_ = readInt32(f, order)

	for i := range ps {
		ps[i].Id = intBuf[i]
	}
}

// ReadGadget reads the gadget particle catalog located at the given location
// and written with the given endianness. Its header and particle sequence
// are returned in a standardized format.
func ReadGadget(path string, order binary.ByteOrder) (*tetra.Header, []tetra.Particle) {
	f, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	gh := &gadgetHeader{}

	_ = readInt32(f, order)
	binary.Read(f, binary.LittleEndian, gh)
	_ = readInt32(f, order)

	h := gh.Standardize()
	floatBuf := make([]float32, 3*h.Count)
	ps := make([]tetra.Particle, h.Count)

	_ = readInt32(f, order)
	binary.Read(f, order, floatBuf)
	_ = readInt32(f, order)

	for i := range ps {
		ps[i].Xs[0] = gh.WrapDistance(float64(floatBuf[3*i+0]))
		ps[i].Xs[1] = gh.WrapDistance(float64(floatBuf[3*i+1]))
		ps[i].Xs[2] = gh.WrapDistance(float64(floatBuf[3*i+2]))
	}

	_ = readInt32(f, order)
	binary.Read(f, order, floatBuf)
	_ = readInt32(f, order)

	rootA := float32(math.Sqrt(float64(gh.Time)))
	for i := range ps {
		ps[i].Vs[0] = float64(floatBuf[3*i+0] * rootA)
		ps[i].Vs[1] = float64(floatBuf[3*i+1] * rootA)
		ps[i].Vs[2] = float64(floatBuf[3*i+2] * rootA)
	}

	ids := make([]int64, h.Count)

	_ = readInt32(f, order)
	binary.Read(f, order, ids)
	_ = readInt32(f, order)

	for i := range ps {
		ps[i].Id = ids[i]
	}

	return h, ps
}

// Write writes the given header and particle sequence to the specified file.
func Write(path string, h *tetra.Header, ps []tetra.Particle) {
	f, err := os.Create(path)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	h.Count = int64(len(ps))
	order := endianness(DefaultEndiannessFlag)

	err = binary.Write(f, order, DefaultEndiannessFlag)
	if err != nil {
		panic(err.Error())
	}
	err = binary.Write(f, order, int32(unsafe.Sizeof(tetra.Header{})))
	if err != nil {
		panic(err.Error())
	}
	err = binary.Write(f, order, int32(unsafe.Sizeof(ps[0])))
	if err != nil {
		panic(err.Error())
	}
	err = binary.Write(f, order, h)
	if err != nil {
		panic(err.Error())
	}
	err = binary.Write(f, order, ps)
	if err != nil {
		panic(err.Error())
	}
}

// readHeader reads only the header from the given file.
func readHeader(path string, flag int) (*tetra.Header, *os.File, binary.ByteOrder) {
	f, err := os.OpenFile(path, flag, os.ModePerm)
	if err != nil {
		panic(err)
	}

	order := endianness(readInt32(f, binary.LittleEndian))

	// Sanity checks:
	headerSize := readInt32(f, order)
	particleSize := readInt32(f, order)
	if int32(unsafe.Sizeof(tetra.Header{})) != headerSize {
		panic(fmt.Sprintf(
			"Size of header in code, %d, does not match size in catalog, %d.",
			unsafe.Sizeof(tetra.Header{}), headerSize,
		))
	} else if int32(unsafe.Sizeof(tetra.Particle{})) != particleSize {
		panic(fmt.Sprintf(
			"Size of header in code, %d, does not match size in catalog, %d.",
			unsafe.Sizeof(tetra.Particle{}), particleSize,
		))
	}

	h := &tetra.Header{}
	err = binary.Read(f, order, h)
	if err != nil {
		panic(err.Error())
	}

	return h, f, order
}

func ReadHeader(path string) *tetra.Header {
	h, f, _ := readHeader(path, os.O_RDONLY)
	if err := f.Close(); err != nil {
		panic(err)
	}
	return h
}

// Append appends a particle sequence to the end of the given file.
func Append(path string, ps []tetra.Particle) {
	if len(ps) == 0 {
		return
	}

	h, f, order := readHeader(path, os.O_RDWR)
	defer f.Close()

	_, err := f.Seek(0, 2)
	if err != nil {
		panic(err.Error())
	}
	err = binary.Write(f, order, ps)
	if err != nil {
		panic(err.Error())
	}

	_, err = f.Seek(12, 0)
	if err != nil {
		panic(err.Error())
	}
	h.Count += int64(len(ps))
	err = binary.Write(f, order, h)
	if err != nil {
		panic(err.Error())
	}
}

// Read reads a header and particle sequence from the given file.
func ReadParticlesAt(path string, ps []tetra.Particle) {
	h, f, order := readHeader(path, os.O_RDONLY)
	defer f.Close()

	if int64(len(ps)) != h.Count {
		panic("Incorrect Particle buffer length.")
	}

	err := binary.Read(f, order, ps)
	if err != nil {
		panic(err.Error())
	}
}

// endianness is a utility function converting an endianness flag to a
// byte order.
func endianness(flag int32) binary.ByteOrder {
	if flag == 0 {
		return binary.LittleEndian
	} else if flag == -1 {
		return binary.BigEndian
	} else {
		panic("Unrecognized endianness flag.")
	}
}
<|endoftext|>


<commit_before>package engine

import (
	"fmt"

	"github.com/proullon/ramsql/engine/log"
	"github.com/proullon/ramsql/engine/parser"
)

// Domain is the set of allowable values for an Attribute.
type Domain struct {
}

// Attribute is a named column of a relation
// AKA Field
// AKA Column
type Attribute struct {
	name          string
	typeName      string
	typeInstance  interface{}
	defaultValue  interface{}
	domain        Domain
	autoIncrement bool
}

func parseAttribute(decl *parser.Decl) (Attribute, error) {
	attr := Attribute{}

	// Attribute name
	if decl.Token != parser.StringToken {
		return attr, fmt.Errorf("engine: expected attribute name, got %v", decl.Token)
	}
	attr.name = decl.Lexeme

	// Attribute type
	if len(decl.Decl) < 1 {
		return attr, fmt.Errorf("Attribute %s has no type", decl.Lexeme)
	}
	if decl.Decl[0].Token != parser.StringToken {
		return attr, fmt.Errorf("engine: expected attribute type, got %v:%v", decl.Decl[0].Token, decl.Decl[0].Lexeme)
	}
	attr.typeName = decl.Decl[0].Lexeme

	// Maybe domain and special thing like primary key
	typeDecl := decl.Decl[1:]
	for i := range typeDecl {
		log.Debug("Got %v for %s %s", typeDecl[i], attr.name, attr.typeName)
		if typeDecl[i].Token == parser.AutoincrementToken {
			attr.autoIncrement = true
		}
	}

	return attr, nil
}

// NewAttribute initialize a new Attribute struct
func NewAttribute(name string, typeName string, autoIncrement bool) Attribute {
	a := Attribute{
		name:          name,
		typeName:      typeName,
		autoIncrement: autoIncrement,
	}

	return a
}
<commit_msg>fix (types): if attribute type is bigserial, then it's auto incrementing<commit_after>package engine

import (
	"fmt"

	"github.com/proullon/ramsql/engine/log"
	"github.com/proullon/ramsql/engine/parser"
)

// Domain is the set of allowable values for an Attribute.
type Domain struct {
}

// Attribute is a named column of a relation
// AKA Field
// AKA Column
type Attribute struct {
	name          string
	typeName      string
	typeInstance  interface{}
	defaultValue  interface{}
	domain        Domain
	autoIncrement bool
}

func parseAttribute(decl *parser.Decl) (Attribute, error) {
	attr := Attribute{}

	// Attribute name
	if decl.Token != parser.StringToken {
		return attr, fmt.Errorf("engine: expected attribute name, got %v", decl.Token)
	}
	attr.name = decl.Lexeme

	// Attribute type
	if len(decl.Decl) < 1 {
		return attr, fmt.Errorf("Attribute %s has no type", decl.Lexeme)
	}
	if decl.Decl[0].Token != parser.StringToken {
		return attr, fmt.Errorf("engine: expected attribute type, got %v:%v", decl.Decl[0].Token, decl.Decl[0].Lexeme)
	}
	attr.typeName = decl.Decl[0].Lexeme

	// Maybe domain and special thing like primary key
	typeDecl := decl.Decl[1:]
	for i := range typeDecl {
		log.Debug("Got %v for %s %s", typeDecl[i], attr.name, attr.typeName)
		if typeDecl[i].Token == parser.AutoincrementToken {
			attr.autoIncrement = true
		}
	}

	if attr.typeName == "bigserial" {
		attr.autoIncrement = true
	}

	return attr, nil
}

// NewAttribute initialize a new Attribute struct
func NewAttribute(name string, typeName string, autoIncrement bool) Attribute {
	a := Attribute{
		name:          name,
		typeName:      typeName,
		autoIncrement: autoIncrement,
	}

	return a
}
<|endoftext|>


<commit_before>package engine

import (
	"bytes"
	"crypto/md5"
	"encoding/binary"
	"encoding/gob"
	"encoding/hex"
	"fmt"
	"os"
	"os/signal"
	"os/user"
	"path"
	"reflect"
	"strconv"
	"syscall"

	"github.com/boltdb/bolt"
	"github.com/denkhaus/tcgl/applog"
)

////////////////////////////////////////////////////////////////////////////////
type DataStore struct {
	db         *bolt.DB
	bucketName []byte
}

////////////////////////////////////////////////////////////////////////////////
var (
	ErrNotFound = fmt.Errorf("Datastore:: value not found")
)

////////////////////////////////////////////////////////////////////////////////
func NewDatastore(path, bucket string) (*DataStore, error) {
	db, err := bolt.Open(path, 0600, nil)
	if err != nil {
		return nil, err
	}

	if err = db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists([]byte(bucket))
		return err
	}); err != nil {
		return nil, err
	}

	store := &DataStore{
		db:         db,
		bucketName: []byte(bucket),
	}

	go store.signalHandler()
	return store, nil
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) signalHandler() {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT)

	<-sigChan

	if d.db != nil {
		d.db.Close()
		d.db = nil
		applog.Infof("Store::DB successfull closed")
	}
	os.Exit(0)
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) Close() (err error) {
	err = d.db.Close()
	d.db = nil
	return
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) Delete(key []byte) error {
	return d.db.Update(func(tx *bolt.Tx) error {
		return tx.Bucket(d.bucketName).Delete(key)
	})
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) Get(key []byte) (interface{}, error) {
	var out []byte
	err := d.db.View(func(tx *bolt.Tx) error {
		mmval := tx.Bucket(d.bucketName).Get(key)
		if mmval == nil {
			return ErrNotFound
		}

		out = make([]byte, len(mmval))
		copy(out, mmval)
		return nil
	})
	if err != nil {
		return nil, err
	}

	return out, err
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) Has(key []byte) (bool, error) {
	var found bool
	err := d.db.View(func(tx *bolt.Tx) error {
		val := tx.Bucket(d.bucketName).Get(key)
		found = (val != nil)
		return nil
	})
	return found, err
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) PutRecord(uid uint32, rec interface{}) error {
	if err := d.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(d.bucketName))

		var buf bytes.Buffer
		enc := gob.NewEncoder(&buf)
		if err := enc.Encode(rec); err != nil {
			return err
		}

		key := []byte(strconv.Itoa(int(uid)))
		return b.Put(key, buf.Bytes())
	}); err != nil {
		return err
	}

	return nil
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) GetRecordById(uid uint32, rec interface{}) error {
	sv := reflect.ValueOf(rec)
	if sv.Kind() != reflect.Ptr {
		return fmt.Errorf("GetRecordById:: rec must be a value ptr.")
	}
	if sv.IsNil() {
		return fmt.Errorf("GetRecordById:: rec must not be nil.")
	}

	var buf bytes.Buffer
	dec := gob.NewDecoder(&buf)
	err := d.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(d.bucketName))
		k := []byte(strconv.Itoa(int(uid)))
		if v := b.Get(k); v != nil {
			if _, err := buf.Write(v); err != nil {
				return err
			}
			if err := dec.Decode(rec); err != nil {
				return err
			}
		}
		return nil
	})

	return err
}

////////////////////////////////////////////////////////////////////////////////
func GetDBPathByArgs(args ...interface{}) (string, error) {
	hasher := md5.New()
	for _, arg := range args {
		switch v := arg.(type) {
		case string:
			hasher.Write([]byte(v))
		case int:
			buf := new(bytes.Buffer)
			if err := binary.Write(buf, binary.LittleEndian, int32(v)); err != nil {
				return "", err
			}
			hasher.Write(buf.Bytes())
		default:
			fmt.Errorf("GetDBPathByArgs::Type not supported")
		}
	}

	usr, err := user.Current()
	if err != nil {
		return "", err
	}
	return path.Join(usr.HomeDir, fmt.Sprintf("imapspam%s.db",
		hex.EncodeToString(hasher.Sum(nil)))), nil
}
<commit_msg>make db files hidden<commit_after>package engine

import (
	"bytes"
	"crypto/md5"
	"encoding/binary"
	"encoding/gob"
	"encoding/hex"
	"fmt"
	"os"
	"os/signal"
	"os/user"
	"path"
	"reflect"
	"strconv"
	"syscall"

	"github.com/boltdb/bolt"
	"github.com/denkhaus/tcgl/applog"
)

////////////////////////////////////////////////////////////////////////////////
type DataStore struct {
	db         *bolt.DB
	bucketName []byte
}

////////////////////////////////////////////////////////////////////////////////
var (
	ErrNotFound = fmt.Errorf("Datastore:: value not found")
)

////////////////////////////////////////////////////////////////////////////////
func NewDatastore(path, bucket string) (*DataStore, error) {
	db, err := bolt.Open(path, 0600, nil)
	if err != nil {
		return nil, err
	}

	if err = db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists([]byte(bucket))
		return err
	}); err != nil {
		return nil, err
	}

	store := &DataStore{
		db:         db,
		bucketName: []byte(bucket),
	}

	go store.signalHandler()
	return store, nil
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) signalHandler() {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT)

	<-sigChan

	if d.db != nil {
		d.db.Close()
		d.db = nil
		applog.Infof("Store::DB successfull closed")
	}
	os.Exit(0)
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) Close() (err error) {
	err = d.db.Close()
	d.db = nil
	return
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) Delete(key []byte) error {
	return d.db.Update(func(tx *bolt.Tx) error {
		return tx.Bucket(d.bucketName).Delete(key)
	})
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) Get(key []byte) (interface{}, error) {
	var out []byte
	err := d.db.View(func(tx *bolt.Tx) error {
		mmval := tx.Bucket(d.bucketName).Get(key)
		if mmval == nil {
			return ErrNotFound
		}

		out = make([]byte, len(mmval))
		copy(out, mmval)
		return nil
	})
	if err != nil {
		return nil, err
	}

	return out, err
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) Has(key []byte) (bool, error) {
	var found bool
	err := d.db.View(func(tx *bolt.Tx) error {
		val := tx.Bucket(d.bucketName).Get(key)
		found = (val != nil)
		return nil
	})
	return found, err
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) PutRecord(uid uint32, rec interface{}) error {
	if err := d.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(d.bucketName))

		var buf bytes.Buffer
		enc := gob.NewEncoder(&buf)
		if err := enc.Encode(rec); err != nil {
			return err
		}

		key := []byte(strconv.Itoa(int(uid)))
		return b.Put(key, buf.Bytes())
	}); err != nil {
		return err
	}

	return nil
}

////////////////////////////////////////////////////////////////////////////////
func (d *DataStore) GetRecordById(uid uint32, rec interface{}) error {
	sv := reflect.ValueOf(rec)
	if sv.Kind() != reflect.Ptr {
		return fmt.Errorf("GetRecordById:: rec must be a value ptr.")
	}
	if sv.IsNil() {
		return fmt.Errorf("GetRecordById:: rec must not be nil.")
	}

	var buf bytes.Buffer
	dec := gob.NewDecoder(&buf)
	err := d.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(d.bucketName))
		k := []byte(strconv.Itoa(int(uid)))
		if v := b.Get(k); v != nil {
			if _, err := buf.Write(v); err != nil {
				return err
			}
			if err := dec.Decode(rec); err != nil {
				return err
			}
		}
		return nil
	})

	return err
}

////////////////////////////////////////////////////////////////////////////////
func GetDBPathByArgs(args ...interface{}) (string, error) {
	hasher := md5.New()
	for _, arg := range args {
		switch v := arg.(type) {
		case string:
			hasher.Write([]byte(v))
		case int:
			buf := new(bytes.Buffer)
			if err := binary.Write(buf, binary.LittleEndian, int32(v)); err != nil {
				return "", err
			}
			hasher.Write(buf.Bytes())
		default:
			fmt.Errorf("GetDBPathByArgs::Type not supported")
		}
	}

	usr, err := user.Current()
	if err != nil {
		return "", err
	}
	return path.Join(usr.HomeDir, fmt.Sprintf(".imapspam%s.db",
		hex.EncodeToString(hasher.Sum(nil)))), nil
}
<|endoftext|>


<commit_before>package match

import (
	"fmt"

	"github.com/tisp-lang/tisp/src/lib/ast"
	"github.com/tisp-lang/tisp/src/lib/debug"
	"github.com/tisp-lang/tisp/src/lib/gensym"
	"github.com/tisp-lang/tisp/src/lib/scalar"
)

type desugarer struct {
	lets []interface{}
}

func newDesugarer() *desugarer {
	return &desugarer{nil}
}

func (d *desugarer) desugar(x interface{}) interface{} {
	switch x := x.(type) {
	case ast.App:
		return ast.NewApp(
			d.desugar(x.Function()),
			d.desugar(x.Arguments()).(ast.Arguments),
			x.DebugInfo())
	case ast.Arguments:
		ps := make([]ast.PositionalArgument, 0, len(x.Positionals()))

		for _, p := range x.Positionals() {
			ps = append(ps, d.desugar(p).(ast.PositionalArgument))
		}

		ks := make([]ast.KeywordArgument, 0, len(x.Keywords()))

		for _, k := range x.Keywords() {
			ks = append(ks, d.desugar(k).(ast.KeywordArgument))
		}

		dicts := make([]interface{}, 0, len(x.ExpandedDicts()))

		for _, dict := range x.ExpandedDicts() {
			dicts = append(dicts, d.desugar(dict))
		}

		return ast.NewArguments(ps, ks, dicts)
	case ast.KeywordArgument:
		return ast.NewKeywordArgument(x.Name(), d.desugar(x.Value()))
	case ast.LetFunction:
		ls := make([]interface{}, 0, len(x.Lets()))

		for _, l := range x.Lets() {
			l := d.desugar(l)
			ls = append(ls, append(d.takeLets(), l)...)
		}

		b := d.desugar(x.Body())
		ls = append(ls, d.takeLets()...)

		return ast.NewLetFunction(
			x.Name(),
			x.Signature(),
			ls,
			b,
			x.DebugInfo())
	case ast.LetVar:
		return ast.NewLetVar(x.Name(), d.desugar(x.Expr()))
	case ast.Match:
		cs := make([]ast.MatchCase, 0, len(x.Cases()))

		for _, c := range x.Cases() {
			cs = append(cs, renameBoundNamesInCase(ast.NewMatchCase(c.Pattern(), d.desugar(c.Value()))))
		}

		return app(d.createMatchFunction(cs), d.desugar(x.Value()))
	case ast.Output:
		return ast.NewOutput(d.desugar(x.Expr()), x.Expanded())
	case ast.PositionalArgument:
		return ast.NewPositionalArgument(d.desugar(x.Value()), x.Expanded())
	default:
		return x
	}
}

func (d *desugarer) takeLets() []interface{} {
	ls := d.lets
	d.lets = nil
	return ls
}

func (d *desugarer) letVar(s string, v interface{}) {
	d.lets = append(d.lets, ast.NewLetVar(s, v))
}

func (d *desugarer) createMatchFunction(cs []ast.MatchCase) interface{} {
	arg := gensym.GenSym("match", "argument")
	body := d.desugarCases(arg, cs)

	f := ast.NewLetFunction(
		gensym.GenSym("match", "function"),
		ast.NewSignature([]string{arg}, nil, "", nil, nil, ""),
		d.takeLets(),
		body,
		debug.NewGoInfo(0))

	d.lets = []interface{}{f}

	return f.Name()
}

func (d *desugarer) desugarCases(v interface{}, cs []ast.MatchCase) interface{} {
	css := groupCases(cs)
	ks := []ast.SwitchCase{}

	if cs, ok := css[listPattern]; ok {
		ks = append(ks, ast.NewSwitchCase("list", d.desugarListCases(v, cs)))
	}

	if cs, ok := css[dictPattern]; ok {
		ks = append(ks, ast.NewSwitchCase("dict", d.desugarDictCases(v, cs)))
	}

	dc := interface{}(nil)

	if cs, ok := css[namePattern]; ok {
		dc = d.desugarNameCases(v, cs)
	}

	return ast.NewSwitch(app("typeOf", v), ks, dc)
}

func groupCases(cs []ast.MatchCase) map[patternType][]ast.MatchCase {
	css := map[patternType][]ast.MatchCase{}

	for _, c := range cs {
		t := getPatternType(c.Pattern())
		css[t] = append(css[t], c)
	}

	return css
}

func getPatternType(p interface{}) patternType {
	switch x := p.(type) {
	case string:
		return namePattern
	case ast.App:
		if len(x.Arguments().Positionals()) == 0 {
			return namePattern
		}

		switch x.Function().(string) {
		case "$list":
			return listPattern
		case "$dict":
			return dictPattern
		}
	}

	panic(fmt.Errorf("Invalid pattern: %#v", p))
}

func (d *desugarer) desugarListCases(v interface{}, cs []ast.MatchCase) interface{} {
	panic("Not implemented")
}

func (d *desugarer) desugarDictCases(v interface{}, cs []ast.MatchCase) interface{} {
	panic("Not implemented")
}

func (d *desugarer) desugarNameCases(v interface{}, cs []ast.MatchCase) interface{} {
	dc := interface{}(nil)
	ks := []ast.SwitchCase{}

	for i, c := range cs {
		switch x := c.Pattern().(type) {
		case string:
			isScalar := scalar.Defined(x)

			if !isScalar && i < len(cs)-1 {
				panic(fmt.Errorf("A wildcard pattern is found, but some cases are left"))
			} else if !isScalar {
				d.letVar(x, v)
				dc = c.Value()
				break
			}

			ks = append(ks, ast.NewSwitchCase(x, c.Value()))
		case ast.App:
			s := "$emptyList"

			if x.Function().(string) == "$dict" {
				s = "$emptyDict"
			}

			ks = append(ks, ast.NewSwitchCase(s, c.Value()))
		}
	}

	return ast.NewSwitch(v, ks, dc)
}

func renameBoundNamesInCase(c ast.MatchCase) ast.MatchCase {
	p, ns := newPatternRenamer().rename(c.Pattern())
	return ast.NewMatchCase(p, newValueRenamer(ns).rename(c.Value()))
}

func equalPatterns(p, q interface{}) bool {
	switch x := p.(type) {
	case string:
		y, ok := q.(string)

		if !ok {
			return false
		}

		return x == y
	case ast.App:
		y, ok := q.(ast.App)

		if !ok ||
			x.Function().(string) != y.Function().(string) ||
			len(x.Arguments().Positionals()) != len(y.Arguments().Positionals()) {
			return false
		}

		for i := range x.Arguments().Positionals() {
			p := x.Arguments().Positionals()[i]
			q := y.Arguments().Positionals()[i]

			if p.Expanded() != q.Expanded() || !equalPatterns(p.Value(), q.Value()) {
				return false
			}
		}

		return true
	}

	panic(fmt.Errorf("Invalid pattern: %#v, %#v", p, q))
}
<commit_msg>Implement desugarListCases<commit_after>package match

import (
	"fmt"

	"github.com/tisp-lang/tisp/src/lib/ast"
	"github.com/tisp-lang/tisp/src/lib/debug"
	"github.com/tisp-lang/tisp/src/lib/gensym"
	"github.com/tisp-lang/tisp/src/lib/scalar"
)

type desugarer struct {
	lets []interface{}
}

func newDesugarer() *desugarer {
	return &desugarer{nil}
}

func (d *desugarer) desugar(x interface{}) interface{} {
	switch x := x.(type) {
	case ast.App:
		return ast.NewApp(
			d.desugar(x.Function()),
			d.desugar(x.Arguments()).(ast.Arguments),
			x.DebugInfo())
	case ast.Arguments:
		ps := make([]ast.PositionalArgument, 0, len(x.Positionals()))

		for _, p := range x.Positionals() {
			ps = append(ps, d.desugar(p).(ast.PositionalArgument))
		}

		ks := make([]ast.KeywordArgument, 0, len(x.Keywords()))

		for _, k := range x.Keywords() {
			ks = append(ks, d.desugar(k).(ast.KeywordArgument))
		}

		dicts := make([]interface{}, 0, len(x.ExpandedDicts()))

		for _, dict := range x.ExpandedDicts() {
			dicts = append(dicts, d.desugar(dict))
		}

		return ast.NewArguments(ps, ks, dicts)
	case ast.KeywordArgument:
		return ast.NewKeywordArgument(x.Name(), d.desugar(x.Value()))
	case ast.LetFunction:
		ls := make([]interface{}, 0, len(x.Lets()))

		for _, l := range x.Lets() {
			l := d.desugar(l)
			ls = append(ls, append(d.takeLets(), l)...)
		}

		b := d.desugar(x.Body())
		ls = append(ls, d.takeLets()...)

		return ast.NewLetFunction(
			x.Name(),
			x.Signature(),
			ls,
			b,
			x.DebugInfo())
	case ast.LetVar:
		return ast.NewLetVar(x.Name(), d.desugar(x.Expr()))
	case ast.Match:
		cs := make([]ast.MatchCase, 0, len(x.Cases()))

		for _, c := range x.Cases() {
			cs = append(cs, renameBoundNamesInCase(ast.NewMatchCase(c.Pattern(), d.desugar(c.Value()))))
		}

		return app(d.createMatchFunction(cs), d.desugar(x.Value()))
	case ast.Output:
		return ast.NewOutput(d.desugar(x.Expr()), x.Expanded())
	case ast.PositionalArgument:
		return ast.NewPositionalArgument(d.desugar(x.Value()), x.Expanded())
	default:
		return x
	}
}

func (d *desugarer) takeLets() []interface{} {
	ls := d.lets
	d.lets = nil
	return ls
}

func (d *desugarer) letVar(s string, v interface{}) {
	d.lets = append(d.lets, ast.NewLetVar(s, v))
}

func (d *desugarer) createMatchFunction(cs []ast.MatchCase) interface{} {
	arg := gensym.GenSym("match", "argument")
	body := d.desugarCases(arg, cs)

	f := ast.NewLetFunction(
		gensym.GenSym("match", "function"),
		ast.NewSignature([]string{arg}, nil, "", nil, nil, ""),
		d.takeLets(),
		body,
		debug.NewGoInfo(0))

	d.lets = []interface{}{f}

	return f.Name()
}

func (d *desugarer) desugarCases(v interface{}, cs []ast.MatchCase) interface{} {
	css := groupCases(cs)
	ks := []ast.SwitchCase{}

	if cs, ok := css[listPattern]; ok {
		ks = append(ks, ast.NewSwitchCase("list", d.desugarListCases(v, cs)))
	}

	if cs, ok := css[dictPattern]; ok {
		ks = append(ks, ast.NewSwitchCase("dict", d.desugarDictCases(v, cs)))
	}

	dc := interface{}(nil)

	if cs, ok := css[namePattern]; ok {
		dc = d.desugarNameCases(v, cs)
	}

	return ast.NewSwitch(app("typeOf", v), ks, dc)
}

func groupCases(cs []ast.MatchCase) map[patternType][]ast.MatchCase {
	css := map[patternType][]ast.MatchCase{}

	for _, c := range cs {
		t := getPatternType(c.Pattern())
		css[t] = append(css[t], c)
	}

	return css
}

func getPatternType(p interface{}) patternType {
	switch x := p.(type) {
	case string:
		return namePattern
	case ast.App:
		if len(x.Arguments().Positionals()) == 0 {
			return namePattern
		}

		switch x.Function().(string) {
		case "$list":
			return listPattern
		case "$dict":
			return dictPattern
		}
	}

	panic(fmt.Errorf("Invalid pattern: %#v", p))
}

func (d *desugarer) desugarListCases(v interface{}, cs []ast.MatchCase) interface{} {
	type group struct {
		first interface{}
		cases []ast.MatchCase
	}

	gs := []group{}

	for _, c := range cs {
		ps := c.Pattern().(ast.App).Arguments().Positionals()
		first := ps[0].Value()

		if ps[0].Expanded() {
			panic("Not implemented")
		}

		c = ast.NewMatchCase(
			ast.NewApp("$list", ast.NewArguments(ps[1:], nil, nil), debug.NewGoInfo(0)),
			c.Value())

		groupExist := false

		for i, g := range gs {
			if equalPatterns(first, g.first) {
				groupExist = true
				gs[i].cases = append(gs[i].cases, c)
			}
		}

		if !groupExist {
			gs = append(gs, group{first, []ast.MatchCase{c}})
		}
	}

	ks := make([]ast.MatchCase, 0, len(gs))

	for _, g := range gs {
		ks = append(ks, ast.NewMatchCase(g.first, d.desugarCases(app("rest", v), g.cases)))
	}

	return d.desugarCases(app("first", v), ks)
}

func (d *desugarer) desugarDictCases(v interface{}, cs []ast.MatchCase) interface{} {
	panic("Not implemented")
}

func (d *desugarer) desugarNameCases(v interface{}, cs []ast.MatchCase) interface{} {
	dc := interface{}(nil)
	ks := []ast.SwitchCase{}

	for i, c := range cs {
		switch x := c.Pattern().(type) {
		case string:
			isScalar := scalar.Defined(x)

			if !isScalar && i < len(cs)-1 {
				panic(fmt.Errorf("A wildcard pattern is found, but some cases are left"))
			} else if !isScalar {
				d.letVar(x, v)
				dc = c.Value()
				break
			}

			ks = append(ks, ast.NewSwitchCase(x, c.Value()))
		case ast.App:
			s := "$emptyList"

			if x.Function().(string) == "$dict" {
				s = "$emptyDict"
			}

			ks = append(ks, ast.NewSwitchCase(s, c.Value()))
		}
	}

	return ast.NewSwitch(v, ks, dc)
}

func renameBoundNamesInCase(c ast.MatchCase) ast.MatchCase {
	p, ns := newPatternRenamer().rename(c.Pattern())
	return ast.NewMatchCase(p, newValueRenamer(ns).rename(c.Value()))
}

func equalPatterns(p, q interface{}) bool {
	switch x := p.(type) {
	case string:
		y, ok := q.(string)

		if !ok {
			return false
		}

		return x == y
	case ast.App:
		y, ok := q.(ast.App)

		if !ok ||
			x.Function().(string) != y.Function().(string) ||
			len(x.Arguments().Positionals()) != len(y.Arguments().Positionals()) {
			return false
		}

		for i := range x.Arguments().Positionals() {
			p := x.Arguments().Positionals()[i]
			q := y.Arguments().Positionals()[i]

			if p.Expanded() != q.Expanded() || !equalPatterns(p.Value(), q.Value()) {
				return false
			}
		}

		return true
	}

	panic(fmt.Errorf("Invalid pattern: %#v, %#v", p, q))
}
<|endoftext|>


<commit_before>package controllers

import (
	"github.com/julienschmidt/httprouter"
	"github.com/raggaer/castro/app/util"
	"net/http"
)

func ExtensionStatic(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	// Get extension identifier
	id := ps.ByName("id")

	// Check if static file exists
	dir, exists := util.ExtensionStatic.FileExists(id)

	if !exists {
		w.WriteHeader(404)
		return
	}

	// Open desired file
	f, err := dir.Open(ps.ByName("filepath"))

	if err != nil {
		w.WriteHeader(404)
		return
	}

	// Close file handle
	defer f.Close()

	// Get file information
	fi, err := f.Stat()

	if err != nil {
		w.WriteHeader(404)
		return
	}

	// Check if file is directory
	if fi.IsDir() {
		w.WriteHeader(404)
		return
	}

	// Serve file
	http.ServeContent(w, req, ps.ByName("*filepath"), fi.ModTime(), f)
}
<commit_msg>Fix filepath typo<commit_after>package controllers

import (
	"github.com/julienschmidt/httprouter"
	"github.com/raggaer/castro/app/util"
	"net/http"
)

func ExtensionStatic(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	// Get extension identifier
	id := ps.ByName("id")

	// Check if static file exists
	dir, exists := util.ExtensionStatic.FileExists(id)

	if !exists {
		w.WriteHeader(404)
		return
	}

	// Open desired file
	f, err := dir.Open(ps.ByName("filepath"))

	if err != nil {
		w.WriteHeader(404)
		return
	}

	// Close file handle
	defer f.Close()

	// Get file information
	fi, err := f.Stat()

	if err != nil {
		w.WriteHeader(404)
		return
	}

	// Check if file is directory
	if fi.IsDir() {
		w.WriteHeader(404)
		return
	}

	// Serve file
	http.ServeContent(w, req, ps.ByName("filepath"), fi.ModTime(), f)
}
<|endoftext|>


<commit_before><commit_msg>fix filer starting under "weed server" when ip is not localhost<commit_after><|endoftext|>


<commit_before>// safe-renamer transliterates file names to ASCII-equivalent with no spaces for easier processing.
package main

import (
	"flag"
	"fmt"
	"github.com/fiam/gounidecode/unidecode"
	"log"
	"os"
	"path"
	"regexp"
)

func main() {
	// Parse flags.
	file := flag.String("file", "", "Name of file to rename")
	commit := flag.Bool("commit", false, "Commit the changes by actually renaming the file")
	flag.Parse()

	// Check arguments.
	if *file == "" {
		log.Fatal("Missing -file argument")
	}

	// Check that source file exists.
	if _, err := os.Stat(*file); err != nil {
		log.Fatal("Source file " + *file + " does not exist")
	}

	// Do processing.
	dir := path.Dir(*file)
	base := path.Base(*file)

	// Transliterate Unicode to ASCII.
	safeBase := unidecode.Unidecode(base)

	// Replace initial hyphen with underscore for argument safety.
	if safeBase[0] == '-' {
		safeBase = "_" + safeBase[1:]
	}

	// Remove any characters that are not word, dash, or dot.
	re := regexp.MustCompile(`[^\w.-]`)
	safeBase = re.ReplaceAllLiteralString(safeBase, "_")

	// Only output information if the file is being renamed.
	if safeBase != base {
		// Create new joined path in same dir location.
		joined := path.Join(dir, safeBase)

		// Abort with error message if new joined path already exists.
		if _, err := os.Stat(joined); err == nil {
			log.Fatal("Target file " + safeBase + " already exists")
		}
		if *commit {
			err := os.Rename(*file, joined)
			if err == nil {
				fmt.Printf("Renamed %s to %s\n", base, safeBase)
			} else {
				log.Fatal("Unable to rename file")
			}
		} else {
			fmt.Printf("Renaming %s to %s\n", base, safeBase)
		}
	}
}
<commit_msg>Fixing command syntax<commit_after>// safe-renamer transliterates file names to ASCII-equivalent with no spaces for easier processing.
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path"
	"regexp"

	"github.com/fiam/gounidecode/unidecode"
)

func main() {
	// Parse flags.
	commit := flag.Bool("commit", false, "Commit the changes by actually renaming the file")
	flag.Parse()

	// Check arguments.
	if len(flag.Args()) < 1 {
		log.Fatal("Missing filename argument")
	}
	file := flag.Arg(0)

	// Check that source file exists.
	if _, err := os.Stat(file); err != nil {
		log.Fatal("Source file " + file + " does not exist")
	}

	// Do processing.
	dir := path.Dir(file)
	base := path.Base(file)

	// Transliterate Unicode to ASCII.
	safeBase := unidecode.Unidecode(base)

	// Replace initial hyphen with underscore for argument safety.
	if safeBase[0] == '-' {
		safeBase = "_" + safeBase[1:]
	}

	// Remove any characters that are not word, dash, or dot.
	re := regexp.MustCompile(`[^\w.-]`)
	safeBase = re.ReplaceAllLiteralString(safeBase, "_")

	// Only output information if the file is being renamed.
	if safeBase != base {
		// Create new joined path in same dir location.
		joined := path.Join(dir, safeBase)

		// Abort with error message if new joined path already exists.
		if _, err := os.Stat(joined); err == nil {
			log.Fatal("Target file " + safeBase + " already exists")
		}
		if *commit {
			err := os.Rename(file, joined)
			if err == nil {
				fmt.Printf("Renamed %s to %s\n", base, safeBase)
			} else {
				log.Fatal("Unable to rename file")
			}
		} else {
			fmt.Printf("Renaming %s to %s\n", base, safeBase)
		}
	}
}
<|endoftext|>