<commit_before>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

// To enable debug output when testing, use "go test -debug"

package parse

import (
	"encoding/json"
	"github.com/demizer/go-elog"
	"reflect"
	"strings"
	"testing"
)

var lexParseTests LexTests

func TestSectionLevelsAdd(t *testing.T) {
	var p sectionLevels
	lvl := p.Add('=', true, 5)
	if lvl != 1 {
		t.Errorf("Improper level on first add, Got level: %d, expected: %d", lvl, 1)
	}
}

func TestSectionLevelsString(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	out := p.String()
	expect := "level: 1, rune: '=', overline: true, length: 5\nlevel: 2, rune: '-', " +
		"overline: true, length: 8\nlevel: 3, rune: '~', overline: false, length: 6\n"
	if out != expect {
		t.Errorf("String output mismatch!\nExpect:\n\n\t%q,\nGot:\n\n\t%q\n", expect, out)
	}
}

func TestSectionLevelsFind(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Find('-')
	if lvl == -1 {
		t.Errorf("Level not found!\nExpect:\n\n\t%d\nGot:\n\n\t%t\n", 2, lvl)
	}
	if lvl != 2 {
		t.Errorf("Level not correct!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 2, lvl)
	}
}

func TestSectionLevelsFindNoResult(t *testing.T) {
	var p sectionLevels
	lvl := p.Find('-')
	if lvl > 0 {
		t.Errorf("Should not find any levels!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", -1, lvl)
	}
}

func TestSectionLevelsLevelEmpty(t *testing.T) {
	var p sectionLevels
	lvl := p.Level()
	expect := 0
	if lvl != expect {
		t.Errorf("Empty sectionLevels should return \"%d\"!\nExpect:\t%d\nGot:\t%d\n",
			expect, expect, lvl)
	}

}

func TestSectionLevelsLevel(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Level()
	if lvl != 3 {
		t.Errorf("Level() returned incorrect level!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 3, lvl)
	}
}

func parseTest(t *testing.T, testName string) (tree *Tree) {
	var err error
	var errs []error
	if lexParseTests == nil {
		lexParseTests, err = ParseTestData("../testdata/test_lex_sections.dat")
		if err != nil {
			t.Fatal(err)
		}
	}
	test := lexParseTests.SearchByName(testName)
	if test != nil {
		log.Debugf("Test Name: %s\n", test.name)
		log.Debugf("Description: %s\n", test.description)
		log.Debugf("Test Input:\n-----------\n%s\n----------\n", test.data)
		tree, errs = Parse(test.name, test.data)
		if errs != nil {
			for _, err := range errs {
				t.Error(err)
			}
		}
	} else {
		t.Fatalf("%q not found!", testName)
	}
	return
}

type checkNode struct {
	t          *testing.T
	testName   string
	pNodeName  string
	pFieldName string
	pFieldVal  interface{}
	pFieldType reflect.Type
	eFieldName string
	eFieldVal  interface{}
	eFieldType reflect.Type
	id         int
}

func (c *checkNode) error(args ...interface{}) {
	c.t.Error(args...)
}

func (c *checkNode) errorf(format string, args ...interface{}) {
	c.t.Errorf(format, args...)
}

func (c *checkNode) dError() {
	if c.pFieldName == "Rune" {
		c.t.Errorf("Got: %s.%s = %#v (%v) (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
			c.pNodeName, c.pFieldName, c.pFieldVal, string(c.pFieldVal.(int32)),
			c.pFieldType, c.id, "#parse-tree", c.eFieldName, c.eFieldVal, c.eFieldType)
		return
	}
	c.t.Errorf("Got: %s.%s = %#v (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
		c.pNodeName, c.pFieldName, c.pFieldVal, c.pFieldType, c.id, "#parse-tree",
		c.eFieldName, c.eFieldVal, c.eFieldType)
}

func (c *checkNode) updateState(pVal reflect.Value, eVal interface{}, field int) bool {
	// Actual parsed metadata
	c.pNodeName = pVal.Type().Name()
	c.pFieldName = pVal.Type().Field(field).Name
	c.pFieldVal = pVal.Field(field).Interface()
	c.pFieldType = pVal.Type().Field(field).Type
	c.id = pVal.FieldByName("Id").Interface().(int)

	// Expected parser metadata
	c.eFieldName = strings.ToLower(string(c.pFieldName[0])) + c.pFieldName[1:]
	c.eFieldVal = eVal.(map[string]interface{})[c.eFieldName]
	c.eFieldType = reflect.TypeOf(c.eFieldVal)

	pField := pVal.Field(field)
	if pField.Kind() == reflect.Ptr && pField.IsNil() {
		// Overline adornment nodes can be null
		if c.pFieldName == "OverLine" {
			return false
		} else {
			c.dError()
			return false
		}
	} else if c.pFieldVal == nil {
		c.dError()
		return false
	}

	return true
}

func (c *checkNode) checkFields(pNode Node, expect interface{}) {
	pVal := reflect.ValueOf(pNode).Elem()
	for i := 0; i < pVal.NumField(); i++ {

		if c.updateState(pVal, expect, i) == false {
			continue
		}

		switch c.pFieldName {
		case "Type":
			if c.pFieldVal.(NodeType).String() != c.eFieldVal {
				c.dError()
			}
		case "Id", "Level", "Length":
			if float64(c.pFieldVal.(int)) != c.eFieldVal {
				c.dError()
			}
		case "Line":
			if float64(c.pFieldVal.(Line)) != c.eFieldVal {
				c.dError()
			}
		case "StartPosition":
			if float64(c.pFieldVal.(StartPosition)) != c.eFieldVal {
				c.dError()
			}
		case "OverLine", "UnderLine":
			c.checkFields(c.pFieldVal.(Node), c.eFieldVal)
		case "NodeList":
			for num, node := range c.pFieldVal.(NodeList) {
				// A little hackery to make our recursion easy
				eFieldVal := c.eFieldVal
				c.checkFields(node.(Node), eFieldVal.([]interface{})[num])
				c.eFieldVal = eFieldVal
			}
		case "Rune":
			if string(c.pFieldVal.(rune)) != c.eFieldVal {
				c.dError()
			}
		default:
			if c.pFieldVal != c.eFieldVal {
				c.dError()
			}
		}
	}

}

func checkParseNodes(t *testing.T, pNodes *NodeList, testName string) {
	test := lexParseTests.SearchByName(testName)
	if len(strings.Trim(test.expectTree, "\n")) == 0 {
		t.Fatal("#parse-tree not found for", testName)
	}
	var nodeList []interface{}
	err := json.Unmarshal([]byte(test.expectTree), &nodeList)
	if err != nil {
		t.Fatal(err)
	}
	state := &checkNode{t: t, testName: testName}
	for pNum, pNode := range *pNodes {
		state.checkFields(pNode, nodeList[pNum])
	}
	return
}

func TestParseSectionTitlePara(t *testing.T) {
	testName := "SectionTitlePara"
	tree := parseTest(t, testName)
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionTitleParaNoBlankLine(t *testing.T) {
	testName := "SectionTitleParaNoBlankLine"
	tree := parseTest(t, testName)
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionParaHeadPara(t *testing.T) {
	testName := "SectionParaHeadPara"
	tree := parseTest(t, testName)
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionUnexpectedTitles(t *testing.T) {
	testName := "SectionUnexpectedTitles"
	tree := parseTest(t, testName)
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionLevelTest1(t *testing.T) {
	testName := "SectionLevelTest1"
	tree := parseTest(t, testName)
	checkParseNodes(t, tree.Nodes, testName)
}
<commit_msg>parse_test.go: Reorder tests<commit_after>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

// To enable debug output when testing, use "go test -debug"

package parse

import (
	"encoding/json"
	"github.com/demizer/go-elog"
	"reflect"
	"strings"
	"testing"
)

var lexParseTests LexTests

func TestSectionLevelsAdd(t *testing.T) {
	var p sectionLevels
	lvl := p.Add('=', true, 5)
	if lvl != 1 {
		t.Errorf("Improper level on first add, Got level: %d, expected: %d", lvl, 1)
	}
}

func TestSectionLevelsString(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	out := p.String()
	expect := "level: 1, rune: '=', overline: true, length: 5\nlevel: 2, rune: '-', " +
		"overline: true, length: 8\nlevel: 3, rune: '~', overline: false, length: 6\n"
	if out != expect {
		t.Errorf("String output mismatch!\nExpect:\n\n\t%q,\nGot:\n\n\t%q\n", expect, out)
	}
}

func TestSectionLevelsFind(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Find('-')
	if lvl == -1 {
		t.Errorf("Level not found!\nExpect:\n\n\t%d\nGot:\n\n\t%t\n", 2, lvl)
	}
	if lvl != 2 {
		t.Errorf("Level not correct!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 2, lvl)
	}
}

func TestSectionLevelsFindNoResult(t *testing.T) {
	var p sectionLevels
	lvl := p.Find('-')
	if lvl > 0 {
		t.Errorf("Should not find any levels!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", -1, lvl)
	}
}

func TestSectionLevelsLevelEmpty(t *testing.T) {
	var p sectionLevels
	lvl := p.Level()
	expect := 0
	if lvl != expect {
		t.Errorf("Empty sectionLevels should return \"%d\"!\nExpect:\t%d\nGot:\t%d\n",
			expect, expect, lvl)
	}

}

func TestSectionLevelsLevel(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Level()
	if lvl != 3 {
		t.Errorf("Level() returned incorrect level!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 3, lvl)
	}
}

func parseTest(t *testing.T, testName string) (tree *Tree) {
	var err error
	var errs []error
	if lexParseTests == nil {
		lexParseTests, err = ParseTestData("../testdata/test_lex_sections.dat")
		if err != nil {
			t.Fatal(err)
		}
	}
	test := lexParseTests.SearchByName(testName)
	if test != nil {
		log.Debugf("Test Name: %s\n", test.name)
		log.Debugf("Description: %s\n", test.description)
		log.Debugf("Test Input:\n-----------\n%s\n----------\n", test.data)
		tree, errs = Parse(test.name, test.data)
		if errs != nil {
			for _, err := range errs {
				t.Error(err)
			}
		}
	} else {
		t.Fatalf("%q not found!", testName)
	}
	return
}

type checkNode struct {
	t          *testing.T
	testName   string
	pNodeName  string
	pFieldName string
	pFieldVal  interface{}
	pFieldType reflect.Type
	eFieldName string
	eFieldVal  interface{}
	eFieldType reflect.Type
	id         int
}

func (c *checkNode) error(args ...interface{}) {
	c.t.Error(args...)
}

func (c *checkNode) errorf(format string, args ...interface{}) {
	c.t.Errorf(format, args...)
}

func (c *checkNode) dError() {
	if c.pFieldName == "Rune" {
		c.t.Errorf("Got: %s.%s = %#v (%v) (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
			c.pNodeName, c.pFieldName, c.pFieldVal, string(c.pFieldVal.(int32)),
			c.pFieldType, c.id, "#parse-tree", c.eFieldName, c.eFieldVal, c.eFieldType)
		return
	}
	c.t.Errorf("Got: %s.%s = %#v (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
		c.pNodeName, c.pFieldName, c.pFieldVal, c.pFieldType, c.id, "#parse-tree",
		c.eFieldName, c.eFieldVal, c.eFieldType)
}

func (c *checkNode) updateState(pVal reflect.Value, eVal interface{}, field int) bool {
	// Actual parsed metadata
	c.pNodeName = pVal.Type().Name()
	c.pFieldName = pVal.Type().Field(field).Name
	c.pFieldVal = pVal.Field(field).Interface()
	c.pFieldType = pVal.Type().Field(field).Type
	c.id = pVal.FieldByName("Id").Interface().(int)

	// Expected parser metadata
	c.eFieldName = strings.ToLower(string(c.pFieldName[0])) + c.pFieldName[1:]
	c.eFieldVal = eVal.(map[string]interface{})[c.eFieldName]
	c.eFieldType = reflect.TypeOf(c.eFieldVal)

	pField := pVal.Field(field)
	if pField.Kind() == reflect.Ptr && pField.IsNil() {
		// Overline adornment nodes can be null
		if c.pFieldName == "OverLine" {
			return false
		} else {
			c.dError()
			return false
		}
	} else if c.pFieldVal == nil {
		c.dError()
		return false
	}

	return true
}

func (c *checkNode) checkFields(pNode Node, expect interface{}) {
	pVal := reflect.ValueOf(pNode).Elem()
	for i := 0; i < pVal.NumField(); i++ {

		if c.updateState(pVal, expect, i) == false {
			continue
		}

		switch c.pFieldName {
		case "Type":
			if c.pFieldVal.(NodeType).String() != c.eFieldVal {
				c.dError()
			}
		case "Id", "Level", "Length":
			if float64(c.pFieldVal.(int)) != c.eFieldVal {
				c.dError()
			}
		case "Line":
			if float64(c.pFieldVal.(Line)) != c.eFieldVal {
				c.dError()
			}
		case "StartPosition":
			if float64(c.pFieldVal.(StartPosition)) != c.eFieldVal {
				c.dError()
			}
		case "OverLine", "UnderLine":
			c.checkFields(c.pFieldVal.(Node), c.eFieldVal)
		case "NodeList":
			for num, node := range c.pFieldVal.(NodeList) {
				// A little hackery to make our recursion easy
				eFieldVal := c.eFieldVal
				c.checkFields(node.(Node), eFieldVal.([]interface{})[num])
				c.eFieldVal = eFieldVal
			}
		case "Rune":
			if string(c.pFieldVal.(rune)) != c.eFieldVal {
				c.dError()
			}
		default:
			if c.pFieldVal != c.eFieldVal {
				c.dError()
			}
		}
	}

}

func checkParseNodes(t *testing.T, pNodes *NodeList, testName string) {
	test := lexParseTests.SearchByName(testName)
	if len(strings.Trim(test.expectTree, "\n")) == 0 {
		t.Fatal("#parse-tree not found for", testName)
	}
	var nodeList []interface{}
	err := json.Unmarshal([]byte(test.expectTree), &nodeList)
	if err != nil {
		t.Fatal(err)
	}
	state := &checkNode{t: t, testName: testName}
	for pNum, pNode := range *pNodes {
		state.checkFields(pNode, nodeList[pNum])
	}
	return
}

func TestParseSectionTitlePara(t *testing.T) {
	testName := "SectionTitlePara"
	tree := parseTest(t, testName)
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionTitleParaNoBlankLine(t *testing.T) {
	testName := "SectionTitleParaNoBlankLine"
	tree := parseTest(t, testName)
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionParaHeadPara(t *testing.T) {
	testName := "SectionParaHeadPara"
	tree := parseTest(t, testName)
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionLevelTest1(t *testing.T) {
	testName := "SectionLevelTest1"
	tree := parseTest(t, testName)
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionUnexpectedTitles(t *testing.T) {
	testName := "SectionUnexpectedTitles"
	tree := parseTest(t, testName)
	checkParseNodes(t, tree.Nodes, testName)
}

<|endoftext|>


<commit_before>/*
	Script to handle an email response to the reminder.
	Steps:
		1. Get Sender - is it one of the registered senders in queue and are they the hosting group?
		2. Check if they should be responding or if someone is being snarky.
		3. Look for Yes/No/Skip
			3a. Yes - update the order in the group
			3b. No - send an email to the next in line, update group
			3c. Skip - respond with the current turn order for next week
	Notes: Super procedural right now.  I need to clean up the code once I have it working!
	and wow! look at the use of 3 different logging!

*/
package hostqueue

import (
	"appengine"
	"fmt"
	"io/ioutil"
	"log"
	"net/mail"
	"net/http"
    "regexp"
    "strings"
)

func init() {

}

func IncomingMail(w http.ResponseWriter, r *http.Request) {
        ctx := appengine.NewContext(r)
        defer r.Body.Close()

        m, err := mail.ReadMessage(r.Body)
		if err != nil {
			log.Fatal(err)
		}

		from := m.Header.Get("From")
		//clean up responses formatted with a name first.  Ex: 'Ann Addicks <test@test.com>'
		from = strings.Split(from, "<")[1]
		from = strings.Split(from, ">")[0]
		ctx.Infof("from : " + from)
		g, err := findGroup(ctx, from)
		if err != nil {
			log.Fatal(err)
		} else if isValidResponder(from, g) {
			responseRegex := regexp.MustCompile(`(yes\b|no\b|skip\b)(.*?)`)
	        body, err := ioutil.ReadAll(m.Body)

	        if err != nil{
				log.Fatal(err)
			}

	        s := string(body)
	        bodyString := strings.ToLower(s)
	        bodyString = strings.Split(bodyString, "it is your turn to host!")[0]

			switch responseRegex.FindString(bodyString) {
			case "yes":
				// Update the order in the group
	        	hosts := g.Hosts
	        	currentHost := hosts[0]
	        	currentHost.TimesHosted++

	        	hosts = hosts[1:]
	        	hosts = append(hosts, currentHost)
	        	g.Hosts = hosts

	        	g.save(ctx)
	        	ctx.Infof("Match Yes")
			case "no":
				//Send an email to the next in line
		    	hosts := g.Hosts

		    	if(g.Next < (len(hosts) - 1)) {
		    		g.Next++
		    	} else {
		    		g.Next = 0
		    	}

		    	g.save(ctx)
		    	sendReminder(g, r)
		    	ctx.Infof("Match No")
			case "skip":
				//Respond with the current turn order for next week
		    	sendSkipMessage(g, r)
		        ctx.Infof("Match Skip")
			default:
				 ctx.Infof("Could not find yes/no/skip")
			}
		} else {
			ctx.Infof("Sender is not valid")
		}
}

/*Pull all the groups and loop through to find the email address.
  I need to learn more about querying app engines datastore to make this nicer.*/
func findGroup(ctx appengine.Context, from string) (Group, error) {
	groups, err := GetGroups(ctx)
	var g Group
	if err != nil {
		return g, err
	}

	for _, group := range groups {
		for _, host := range group.Hosts {
			if strings.Contains(host.Emails, from) {
				return group, nil
			}
		}
	}
	return g, fmt.Errorf("Cannot find a group for: %s", from)
}

//Check if they should be responding or if someone is being snarky.
func isValidResponder(from string, g Group) bool {
	validEmails := g.Hosts[g.Next].Emails
	return strings.Contains(validEmails, from)
}

//http://stackoverflow.com/questions/10485743/contains-method-for-a-slice
func contains(slice []string, item string) bool {
    set := make(map[string]struct{}, len(slice))
    for _, s := range slice {
        set[s] = struct{}{}
    }

    _, ok := set[item]
    return ok
}
<commit_msg>removed empty init<commit_after>/*
	Script to handle an email response to the reminder.
	Steps:
		1. Get Sender - is it one of the registered senders in queue and are they the hosting group?
		2. Check if they should be responding or if someone is being snarky.
		3. Look for Yes/No/Skip
			3a. Yes - update the order in the group
			3b. No - send an email to the next in line, update group
			3c. Skip - respond with the current turn order for next week
	Notes: Super procedural right now.  I need to clean up the code once I have it working!
	and wow! look at the use of 3 different logging!

*/
package hostqueue

import (
	"appengine"
	"fmt"
	"io/ioutil"
	"log"
	"net/mail"
	"net/http"
    "regexp"
    "strings"
)

func IncomingMail(w http.ResponseWriter, r *http.Request) {
        ctx := appengine.NewContext(r)
        defer r.Body.Close()

        m, err := mail.ReadMessage(r.Body)
		if err != nil {
			log.Fatal(err)
		}

		from := m.Header.Get("From")
		//clean up responses formatted with a name first.  Ex: 'Ann Addicks <test@test.com>'
		from = strings.Split(from, "<")[1]
		from = strings.Split(from, ">")[0]
		ctx.Infof("from : " + from)
		g, err := findGroup(ctx, from)
		if err != nil {
			log.Fatal(err)
		} else if isValidResponder(from, g) {
			responseRegex := regexp.MustCompile(`(yes\b|no\b|skip\b)(.*?)`)
	        body, err := ioutil.ReadAll(m.Body)

	        if err != nil{
				log.Fatal(err)
			}

	        s := string(body)
	        bodyString := strings.ToLower(s)
	        bodyString = strings.Split(bodyString, "it is your turn to host!")[0]

			switch responseRegex.FindString(bodyString) {
			case "yes":
				// Update the order in the group
	        	hosts := g.Hosts
	        	currentHost := hosts[0]
	        	currentHost.TimesHosted++

	        	hosts = hosts[1:]
	        	hosts = append(hosts, currentHost)
	        	g.Hosts = hosts

	        	g.save(ctx)
	        	ctx.Infof("Match Yes")
			case "no":
				//Send an email to the next in line
		    	hosts := g.Hosts

		    	if(g.Next < (len(hosts) - 1)) {
		    		g.Next++
		    	} else {
		    		g.Next = 0
		    	}

		    	g.save(ctx)
		    	sendReminder(g, r)
		    	ctx.Infof("Match No")
			case "skip":
				//Respond with the current turn order for next week
		    	sendSkipMessage(g, r)
		        ctx.Infof("Match Skip")
			default:
				 ctx.Infof("Could not find yes/no/skip")
			}
		} else {
			ctx.Infof("Sender is not valid")
		}
}

/*Pull all the groups and loop through to find the email address.
  I need to learn more about querying app engines datastore to make this nicer.*/
func findGroup(ctx appengine.Context, from string) (Group, error) {
	groups, err := GetGroups(ctx)
	var g Group
	if err != nil {
		return g, err
	}

	for _, group := range groups {
		for _, host := range group.Hosts {
			if strings.Contains(host.Emails, from) {
				return group, nil
			}
		}
	}
	return g, fmt.Errorf("Cannot find a group for: %s", from)
}

//Check if they should be responding or if someone is being snarky.
func isValidResponder(from string, g Group) bool {
	validEmails := g.Hosts[g.Next].Emails
	return strings.Contains(validEmails, from)
}

//http://stackoverflow.com/questions/10485743/contains-method-for-a-slice
func contains(slice []string, item string) bool {
    set := make(map[string]struct{}, len(slice))
    for _, s := range slice {
        set[s] = struct{}{}
    }

    _, ok := set[item]
    return ok
}
<|endoftext|>


<commit_before>package sctp

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func makePayload(tsn uint32, nBytes int) *chunkPayloadData {
	return &chunkPayloadData{tsn: tsn, userData: make([]byte, nBytes)}
}

func TestPayloadQueue(t *testing.T) {
	t.Run("pushNoCheck", func(t *testing.T) {
		pq := newPayloadQueue()
		pq.pushNoCheck(makePayload(0, 10))
		assert.Equal(t, 10, pq.getNumBytes(), "total bytes mismatch")
		assert.Equal(t, 1, pq.size(), "item count mismatch")
		pq.pushNoCheck(makePayload(1, 11))
		assert.Equal(t, 21, pq.getNumBytes(), "total bytes mismatch")
		assert.Equal(t, 2, pq.size(), "item count mismatch")
		pq.pushNoCheck(makePayload(2, 12))
		assert.Equal(t, 33, pq.getNumBytes(), "total bytes mismatch")
		assert.Equal(t, 3, pq.size(), "item count mismatch")

		for i := uint32(0); i < 3; i++ {
			c, ok := pq.pop(i)
			assert.True(t, ok, "pop should succeed")
			if ok {
				assert.Equal(t, i, c.tsn, "TSN should match")
				assert.NotNil(t, pq.sorted, "should not be nil")
			}
		}

		assert.Equal(t, 0, pq.getNumBytes(), "total bytes mismatch")
		assert.Equal(t, 0, pq.size(), "item count mismatch")

		pq.pushNoCheck(makePayload(3, 13))
		assert.Nil(t, pq.sorted, "should be nil")
		assert.Equal(t, 13, pq.getNumBytes(), "total bytes mismatch")
		pq.pushNoCheck(makePayload(4, 14))
		assert.Nil(t, pq.sorted, "should be nil")
		assert.Equal(t, 27, pq.getNumBytes(), "total bytes mismatch")

		for i := uint32(3); i < 5; i++ {
			c, ok := pq.pop(i)
			assert.True(t, ok, "pop should succeed")
			if ok {
				assert.Equal(t, i, c.tsn, "TSN should match")
				assert.NotNil(t, pq.sorted, "should not be nil")
			}
		}

		assert.Equal(t, 0, pq.getNumBytes(), "total bytes mismatch")
		assert.Equal(t, 0, pq.size(), "item count mismatch")
	})

	t.Run("getGapAckBlocks", func(t *testing.T) {
		pq := newPayloadQueue()
		pq.push(makePayload(1, 0), 0)
		pq.push(makePayload(2, 0), 0)
		pq.push(makePayload(3, 0), 0)
		pq.push(makePayload(4, 0), 0)
		pq.push(makePayload(5, 0), 0)
		pq.push(makePayload(6, 0), 0)

		gab1 := []*gapAckBlock{{start: 1, end: 6}}
		gab2 := pq.getGapAckBlocks(0)
		assert.NotNil(t, gab2)
		assert.Len(t, gab2, 1)

		assert.Equal(t, gab1[0].start, gab2[0].start)
		assert.Equal(t, gab1[0].end, gab2[0].end)

		pq.push(makePayload(8, 0), 0)
		pq.push(makePayload(9, 0), 0)

		gab1 = []*gapAckBlock{{start: 1, end: 6}, {start: 8, end: 9}}
		gab2 = pq.getGapAckBlocks(0)
		assert.NotNil(t, gab2)
		assert.Len(t, gab2, 2)

		assert.Equal(t, gab1[0].start, gab2[0].start)
		assert.Equal(t, gab1[0].end, gab2[0].end)
		assert.Equal(t, gab1[1].start, gab2[1].start)
		assert.Equal(t, gab1[1].end, gab2[1].end)
	})

	t.Run("getLastTSNReceived", func(t *testing.T) {
		pq := newPayloadQueue()

		// empty queie should return false
		tsn, ok := pq.getLastTSNReceived()
		assert.False(t, ok, "should be false")

		ok = pq.push(makePayload(20, 0), 0)
		assert.True(t, ok, "should be true")
		tsn, ok = pq.getLastTSNReceived()
		assert.True(t, ok, "should be false")
		assert.Equal(t, uint32(20), tsn, "should match")

		// append should work
		ok = pq.push(makePayload(21, 0), 0)
		assert.True(t, ok, "should be true")
		tsn, ok = pq.getLastTSNReceived()
		assert.True(t, ok, "should be false")
		assert.Equal(t, uint32(21), tsn, "should match")

		// check if sorting applied
		ok = pq.push(makePayload(19, 0), 0)
		assert.True(t, ok, "should be true")
		tsn, ok = pq.getLastTSNReceived()
		assert.True(t, ok, "should be false")
		assert.Equal(t, uint32(21), tsn, "should match")
	})
}
<commit_msg>Fix lint error<commit_after>package sctp

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func makePayload(tsn uint32, nBytes int) *chunkPayloadData {
	return &chunkPayloadData{tsn: tsn, userData: make([]byte, nBytes)}
}

func TestPayloadQueue(t *testing.T) {
	t.Run("pushNoCheck", func(t *testing.T) {
		pq := newPayloadQueue()
		pq.pushNoCheck(makePayload(0, 10))
		assert.Equal(t, 10, pq.getNumBytes(), "total bytes mismatch")
		assert.Equal(t, 1, pq.size(), "item count mismatch")
		pq.pushNoCheck(makePayload(1, 11))
		assert.Equal(t, 21, pq.getNumBytes(), "total bytes mismatch")
		assert.Equal(t, 2, pq.size(), "item count mismatch")
		pq.pushNoCheck(makePayload(2, 12))
		assert.Equal(t, 33, pq.getNumBytes(), "total bytes mismatch")
		assert.Equal(t, 3, pq.size(), "item count mismatch")

		for i := uint32(0); i < 3; i++ {
			c, ok := pq.pop(i)
			assert.True(t, ok, "pop should succeed")
			if ok {
				assert.Equal(t, i, c.tsn, "TSN should match")
				assert.NotNil(t, pq.sorted, "should not be nil")
			}
		}

		assert.Equal(t, 0, pq.getNumBytes(), "total bytes mismatch")
		assert.Equal(t, 0, pq.size(), "item count mismatch")

		pq.pushNoCheck(makePayload(3, 13))
		assert.Nil(t, pq.sorted, "should be nil")
		assert.Equal(t, 13, pq.getNumBytes(), "total bytes mismatch")
		pq.pushNoCheck(makePayload(4, 14))
		assert.Nil(t, pq.sorted, "should be nil")
		assert.Equal(t, 27, pq.getNumBytes(), "total bytes mismatch")

		for i := uint32(3); i < 5; i++ {
			c, ok := pq.pop(i)
			assert.True(t, ok, "pop should succeed")
			if ok {
				assert.Equal(t, i, c.tsn, "TSN should match")
				assert.NotNil(t, pq.sorted, "should not be nil")
			}
		}

		assert.Equal(t, 0, pq.getNumBytes(), "total bytes mismatch")
		assert.Equal(t, 0, pq.size(), "item count mismatch")
	})

	t.Run("getGapAckBlocks", func(t *testing.T) {
		pq := newPayloadQueue()
		pq.push(makePayload(1, 0), 0)
		pq.push(makePayload(2, 0), 0)
		pq.push(makePayload(3, 0), 0)
		pq.push(makePayload(4, 0), 0)
		pq.push(makePayload(5, 0), 0)
		pq.push(makePayload(6, 0), 0)

		gab1 := []*gapAckBlock{{start: 1, end: 6}}
		gab2 := pq.getGapAckBlocks(0)
		assert.NotNil(t, gab2)
		assert.Len(t, gab2, 1)

		assert.Equal(t, gab1[0].start, gab2[0].start)
		assert.Equal(t, gab1[0].end, gab2[0].end)

		pq.push(makePayload(8, 0), 0)
		pq.push(makePayload(9, 0), 0)

		gab1 = []*gapAckBlock{{start: 1, end: 6}, {start: 8, end: 9}}
		gab2 = pq.getGapAckBlocks(0)
		assert.NotNil(t, gab2)
		assert.Len(t, gab2, 2)

		assert.Equal(t, gab1[0].start, gab2[0].start)
		assert.Equal(t, gab1[0].end, gab2[0].end)
		assert.Equal(t, gab1[1].start, gab2[1].start)
		assert.Equal(t, gab1[1].end, gab2[1].end)
	})

	t.Run("getLastTSNReceived", func(t *testing.T) {
		pq := newPayloadQueue()

		// empty queie should return false
		_, ok := pq.getLastTSNReceived()
		assert.False(t, ok, "should be false")

		ok = pq.push(makePayload(20, 0), 0)
		assert.True(t, ok, "should be true")
		tsn, ok := pq.getLastTSNReceived()
		assert.True(t, ok, "should be false")
		assert.Equal(t, uint32(20), tsn, "should match")

		// append should work
		ok = pq.push(makePayload(21, 0), 0)
		assert.True(t, ok, "should be true")
		tsn, ok = pq.getLastTSNReceived()
		assert.True(t, ok, "should be false")
		assert.Equal(t, uint32(21), tsn, "should match")

		// check if sorting applied
		ok = pq.push(makePayload(19, 0), 0)
		assert.True(t, ok, "should be true")
		tsn, ok = pq.getLastTSNReceived()
		assert.True(t, ok, "should be false")
		assert.Equal(t, uint32(21), tsn, "should match")
	})
}
<|endoftext|>


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

//go:generate sh generate.sh

// Command genop generates a Go source file with functions for TensorFlow ops.
package main

import (
	"bytes"
	"flag"
	"go/format"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/tensorflow/tensorflow/tensorflow/go/genop/internal"
)

func main() {
	filename := flag.String("outfile", "", "File to write generated source code to.")
	flag.Parse()
	if *filename == "" {
		log.Fatal("-outfile must be set")
	}
	os.MkdirAll(filepath.Dir(*filename), 0755)

	var buf bytes.Buffer
	if err := internal.GenerateFunctionsForRegisteredOps(&buf); err != nil {
		log.Fatal(err)
	}
	formatted, err := format.Source(buf.Bytes())
	if err != nil {
		log.Fatalf("Failed to generate valid source? 'go fmt' failed: %v", err)
	}
	if err := ioutil.WriteFile(*filename, formatted, 0644); err != nil {
		log.Fatalf("Failed to write to %q: %v", *filename, err)
	}
}
<commit_msg>Go: Enable custom headers in files generated by genop. Change: 146532572<commit_after>// Copyright 2016 The TensorFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:generate sh generate.sh

// Command genop generates a Go source file with functions for TensorFlow ops.
package main

import (
	"bytes"
	"flag"
	"go/format"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/tensorflow/tensorflow/tensorflow/go/genop/internal"
)

func main() {
	var (
		filename = flag.String("outfile", "", "File to write generated source code to.")
		header   = flag.String("header", "", "Path to a file whose contents will be copied into the generated file. Can be empty")
		buf bytes.Buffer
	)
	flag.Parse()
	if *filename == "" {
		log.Fatal("-outfile must be set")
	}
	if *header != "" {
		hdr, err := ioutil.ReadFile(*header)
		if err != nil {
			log.Fatalf("Unable to read %s: %v", *header, err)
		}
		buf.Write(hdr)
		buf.WriteString("\n\n")
	}
	os.MkdirAll(filepath.Dir(*filename), 0755)

	if err := internal.GenerateFunctionsForRegisteredOps(&buf); err != nil {
		log.Fatal(err)
	}
	formatted, err := format.Source(buf.Bytes())
	if err != nil {
		log.Fatalf("Failed to generate valid source? 'go fmt' failed: %v", err)
	}
	if err := ioutil.WriteFile(*filename, formatted, 0644); err != nil {
		log.Fatalf("Failed to write to %q: %v", *filename, err)
	}
}
<|endoftext|>


<commit_before>package app

import (
    "fmt"
    "strings"
    "strconv"
    "monet/db"
    "github.com/hoisie/web.go"
    "monet/template"
    "monet/conf"
    "code.google.com/p/gorilla/sessions"
)

var listPageSize = 15
var indexListSize = 6

var adminBase = template.Base {Path: "admin/base.mustache"}
var store = sessions.NewCookieStore([]byte(conf.Config.SessionSecret))

func AttachAdmin(url string) {
    // auth
    web.Get(url + "login/", login)
    web.Post(url + "login/", login)
    web.Get(url + "logout/", logout)
    // users
    /*  too much unnecessary work?
    web.Get(url + "users/", userList)
    web.Get(url + "users/edit/(.*)", userEdit)
    web.Get(url + "users/delete/(.*)", userDelete)
    web.Get(url + "users/add/", userAdd)
    web.Post(url + "users/add/", userAddPost)
    */
    // posts
    web.Get(url + "unpublished/(\\d+)?", unpublishedList)
    web.Get(url + "posts/(\\d+)?", postList)
    web.Get(url + "posts/edit/(.*)", postEdit)
    web.Post(url + "posts/edit/(.*)", postEdit)
    web.Get(url + "posts/delete/(.*)", postDelete)
    web.Get(url + "posts/add/", postAdd)
    web.Post(url + "posts/add/", postAddPost)
    web.Post(url + "posts/preview/", postPreview)
    // pages
    web.Get(url + "pages/add/", pageAdd)
    web.Post(url + "pages/add/", pageAddPost)
    web.Get(url + "pages/edit/(.*)", pageEdit)
    web.Post(url + "pages/edit/(.*)", pageEdit)
    web.Post(url + "pages/preview/", pagePreview)
    web.Get(url + "pages/delete/(.*)", pageDelete)
    web.Get(url + "pages/(\\d+)?", pageList)

    web.Get(url, adminIndex)
}

func requireAuthentication(ctx *web.Context) bool {
    session,_ := store.Get(ctx.Request, "monet-session")

    if session.Values["authenticated"] != true {
        ctx.Redirect(302, "/admin/login/")
        return true
    }
    return false
}

// views

func login(ctx *web.Context) string {
    if ctx.Params != nil {
        p := ctx.Params
        if db.Users().Validate(p["username"], p["password"]) {
            session,_ := store.Get(ctx.Request, "monet-session")
            session.Values["authenticated"] = true
            session.Save(ctx.Request, ctx.ResponseWriter)
            ctx.Redirect(302, "/admin/")
        }
    }
    return adminBase.Render("admin/login.mustache", ctx.Params, dict{"login":true})
}

func logout(ctx *web.Context) string {
    session,_ := store.Get(ctx.Request, "monet-session")
    session.Values["authenticated"] = false
    session.Save(ctx.Request, ctx.ResponseWriter)
    ctx.Redirect(302, "/admin/login/")
    return ""
}

func adminIndex(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    var posts []db.Post
    var unpublished []db.Post
    var pages []db.Page
    db.Posts().Latest(dict{"published":1}).Limit(indexListSize).Iter().All(&posts)
    db.Posts().Latest(dict{"published":0}).Limit(indexListSize).Iter().All(&unpublished)
    db.Pages().C.Find(nil).Limit(indexListSize).Iter().All(&pages)

    return adminBase.Render("admin/index.mustache", dict{
        "posts": posts, "unpublished": unpublished, "pages": pages})
}

func postEdit(ctx *web.Context, slug string) string {
    if requireAuthentication(ctx) { return "" }
    var post *db.Post
    err := db.Posts().C.Find(dict{"slug":slug}).One(&post)
    if err != nil {
        fmt.Println(err)
        ctx.Redirect(302, "/admin/")
        return ""
    }
    if len(ctx.Params) > 1 {
        post.FromParams(ctx.Params)
        post.Update()
    }

    return adminBase.Render("admin/posts-edit.mustache", post, dict{
        "IsPublished": post.Published == 1,
        "IdHex": post.Id.Hex()})
}

func postList(ctx *web.Context, page string) string {
    if requireAuthentication(ctx) { return "" }
    pageNum := 1
    if len(page) != 0 { pageNum,_ = strconv.Atoi(page) }

    n := listPageSize
    paginator := NewPaginator(pageNum, n)
    paginator.Link = "/admin/posts/"
    cursor := db.Posts()

    var posts []db.Post
    // do a search, if required, of title and content
    var err error
    var numObjects int

    if len(ctx.Params["Search"]) > 0 {
        term := dict{"$regex": ctx.Params["Search"]}
        search := dict{"published":1, "$or": []dict{dict{"title":term}, dict{"content":term}}}
        err = cursor.Latest(search).Skip(paginator.Skip).Limit(n).All(&posts)
        numObjects,_ = cursor.Latest(search).Count()
    } else {
        err = cursor.Latest(dict{"published":1}).Skip(paginator.Skip).
            Limit(n).Iter().All(&posts)
        numObjects,_ = cursor.C.Find(dict{"published":1}).Count()
    }

    if err != nil {
        fmt.Println(err)
    }

    return adminBase.Render("admin/post-list.mustache", dict{
        "Posts": posts, "Pagination": paginator.Render(numObjects)})
}

func unpublishedList(ctx *web.Context, page string) string {
    if requireAuthentication(ctx) { return "" }
    pageNum := 1
    if len(page) != 0 { pageNum,_ = strconv.Atoi(page) }

    paginator := NewPaginator(pageNum, listPageSize)
    paginator.Link = "/admin/unpublished/"
    cursor := db.Posts()
    var posts []db.Post
    latest := cursor.Latest(dict{"published":0})
    latest.Limit(listPageSize).Iter().All(&posts)
    numObjects,_ := latest.Count()
    return adminBase.Render("admin/post-list.mustache", dict{
        "Posts": posts, "Pagination": paginator.Render(numObjects),
        "Unpublished": true})

}

func postAdd(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    return adminBase.Render("admin/posts-edit.mustache", ctx.Params,
        dict{"Published": 0, "IsPublished": false})
}

func postAddPost(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    post := new(db.Post)
    post.FromParams(ctx.Params)
    post.Update()
    ctx.Redirect(302, "/admin/")
    return ""
    //ctx.Redirect(302, "/admin/posts/edit/" + post.Slug + "/")
}

func postPreview(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    var post = new(db.Post)
    post.FromParams(ctx.Params)
    /* not sure the ettiquite here, RenderPost is defined in app.go */
    return RenderPost(post)
}

func postDelete(ctx *web.Context, slug string) string {
    if requireAuthentication(ctx) { return "" }
    db.Posts().C.Remove(dict{"slug": slug})
    ctx.Redirect(302, "/admin/")
    return ""
}

func pageAdd(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    ctx.Params["Url"] = strings.TrimLeft(ctx.Params["Url"], "/")
    return adminBase.Render("admin/pages-edit.mustache", ctx.Params)
}

func pageAddPost(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    var page = new(db.Page)
    page.FromParams(ctx.Params)
    page.Update()
    ctx.Redirect(302, "/admin/")
    return ""
    //ctx.Redirect(302, "/admin/posts/edit/" + post.Slug + "/")
}

func pageEdit(ctx *web.Context, url string) string {
    if requireAuthentication(ctx) { return "" }
    var page *db.Page
    err := db.Pages().C.Find(dict{"url": url}).One(&page)
    if err != nil {
        fmt.Println(err)
        ctx.Redirect(302, "/admin/")
        return ""
    }
    if len(ctx.Params) > 1 {
        page.FromParams(ctx.Params)
        page.Update()
    }
    return adminBase.Render("admin/pages-edit.mustache", page)
}

func pagePreview(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    var page = new(db.Page)
    page.FromParams(ctx.Params)
    return template.RenderMarkdown(page.Content)
}

func pageDelete(ctx *web.Context, url string) string {
    if requireAuthentication(ctx) { return "" }
    db.Pages().C.Remove(dict{"url": url})
    ctx.Redirect(302, "/admin/")
    return ""
}

func pageList(ctx *web.Context, page string) string {
    if requireAuthentication(ctx) { return "" }
    pageNum := 1
    if len(page) != 0 { pageNum,_ = strconv.Atoi(page) }

    n := listPageSize
    paginator := NewPaginator(pageNum, n)
    paginator.Link = "/admin/pages/"
    cursor := db.Pages().C
    sort := dict{"url":1}

    var pages []db.Page
    // do a search, if required, of title and content
    var err error
    var numObjects int

    if len(ctx.Params["Search"]) > 0 {
        term := dict{"$regex": ctx.Params["Search"]}
        search := dict{"$or": []dict{dict{"url":term}, dict{"content":term}}}
        err = cursor.Find(search).Sort(sort).Skip(paginator.Skip).Limit(n).All(&pages)
        numObjects,_ = cursor.Find(search).Count()
    } else {
        err = cursor.Find(nil).Sort(sort).Skip(paginator.Skip).Limit(n).Iter().All(&pages)
        numObjects,_ = cursor.Count()
    }

    if err != nil {
        fmt.Println(err)
    }

    return adminBase.Render("admin/page-list.mustache", dict{
        "Pages": pages, "Pagination": paginator.Render(numObjects)})
}

<commit_msg>fix the post/page delete handlers to redirect back to the referer<commit_after>package app

import (
    "fmt"
    "strings"
    "strconv"
    "monet/db"
    "github.com/hoisie/web.go"
    "monet/template"
    "monet/conf"
    "code.google.com/p/gorilla/sessions"
)

var listPageSize = 15
var indexListSize = 6

var adminBase = template.Base {Path: "admin/base.mustache"}
var store = sessions.NewCookieStore([]byte(conf.Config.SessionSecret))

func AttachAdmin(url string) {
    // auth
    web.Get(url + "login/", login)
    web.Post(url + "login/", login)
    web.Get(url + "logout/", logout)
    // users
    /*  too much unnecessary work?
    web.Get(url + "users/", userList)
    web.Get(url + "users/edit/(.*)", userEdit)
    web.Get(url + "users/delete/(.*)", userDelete)
    web.Get(url + "users/add/", userAdd)
    web.Post(url + "users/add/", userAddPost)
    */
    // posts
    web.Get(url + "unpublished/(\\d+)?", unpublishedList)
    web.Get(url + "posts/(\\d+)?", postList)
    web.Get(url + "posts/edit/(.*)", postEdit)
    web.Post(url + "posts/edit/(.*)", postEdit)
    web.Get(url + "posts/delete/(.*)", postDelete)
    web.Get(url + "posts/add/", postAdd)
    web.Post(url + "posts/add/", postAddPost)
    web.Post(url + "posts/preview/", postPreview)
    // pages
    web.Get(url + "pages/add/", pageAdd)
    web.Post(url + "pages/add/", pageAddPost)
    web.Get(url + "pages/edit/(.*)", pageEdit)
    web.Post(url + "pages/edit/(.*)", pageEdit)
    web.Post(url + "pages/preview/", pagePreview)
    web.Get(url + "pages/delete/(.*)", pageDelete)
    web.Get(url + "pages/(\\d+)?", pageList)

    web.Get(url, adminIndex)
}

func requireAuthentication(ctx *web.Context) bool {
    session,_ := store.Get(ctx.Request, "monet-session")

    if session.Values["authenticated"] != true {
        ctx.Redirect(302, "/admin/login/")
        return true
    }
    return false
}

// views

func login(ctx *web.Context) string {
    if ctx.Params != nil {
        p := ctx.Params
        if db.Users().Validate(p["username"], p["password"]) {
            session,_ := store.Get(ctx.Request, "monet-session")
            session.Values["authenticated"] = true
            session.Save(ctx.Request, ctx.ResponseWriter)
            ctx.Redirect(302, "/admin/")
        }
    }
    return adminBase.Render("admin/login.mustache", ctx.Params, dict{"login":true})
}

func logout(ctx *web.Context) string {
    session,_ := store.Get(ctx.Request, "monet-session")
    session.Values["authenticated"] = false
    session.Save(ctx.Request, ctx.ResponseWriter)
    ctx.Redirect(302, "/admin/login/")
    return ""
}

func adminIndex(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    var posts []db.Post
    var unpublished []db.Post
    var pages []db.Page
    db.Posts().Latest(dict{"published":1}).Limit(indexListSize).Iter().All(&posts)
    db.Posts().Latest(dict{"published":0}).Limit(indexListSize).Iter().All(&unpublished)
    db.Pages().C.Find(nil).Limit(indexListSize).Iter().All(&pages)

    return adminBase.Render("admin/index.mustache", dict{
        "posts": posts, "unpublished": unpublished, "pages": pages})
}

func postEdit(ctx *web.Context, slug string) string {
    if requireAuthentication(ctx) { return "" }
    var post *db.Post
    err := db.Posts().C.Find(dict{"slug":slug}).One(&post)
    if err != nil {
        fmt.Println(err)
        ctx.Redirect(302, "/admin/")
        return ""
    }
    if len(ctx.Params) > 1 {
        post.FromParams(ctx.Params)
        post.Update()
    }

    return adminBase.Render("admin/posts-edit.mustache", post, dict{
        "IsPublished": post.Published == 1,
        "IdHex": post.Id.Hex()})
}

func postList(ctx *web.Context, page string) string {
    if requireAuthentication(ctx) { return "" }
    pageNum := 1
    if len(page) != 0 { pageNum,_ = strconv.Atoi(page) }

    n := listPageSize
    paginator := NewPaginator(pageNum, n)
    paginator.Link = "/admin/posts/"
    cursor := db.Posts()

    var posts []db.Post
    // do a search, if required, of title and content
    var err error
    var numObjects int

    if len(ctx.Params["Search"]) > 0 {
        term := dict{"$regex": ctx.Params["Search"]}
        search := dict{"published":1, "$or": []dict{dict{"title":term}, dict{"content":term}}}
        err = cursor.Latest(search).Skip(paginator.Skip).Limit(n).All(&posts)
        numObjects,_ = cursor.Latest(search).Count()
    } else {
        err = cursor.Latest(dict{"published":1}).Skip(paginator.Skip).
            Limit(n).Iter().All(&posts)
        numObjects,_ = cursor.C.Find(dict{"published":1}).Count()
    }

    if err != nil {
        fmt.Println(err)
    }

    return adminBase.Render("admin/post-list.mustache", dict{
        "Posts": posts, "Pagination": paginator.Render(numObjects)})
}

func unpublishedList(ctx *web.Context, page string) string {
    if requireAuthentication(ctx) { return "" }
    pageNum := 1
    if len(page) != 0 { pageNum,_ = strconv.Atoi(page) }

    paginator := NewPaginator(pageNum, listPageSize)
    paginator.Link = "/admin/unpublished/"
    cursor := db.Posts()
    var posts []db.Post
    latest := cursor.Latest(dict{"published":0})
    latest.Limit(listPageSize).Iter().All(&posts)
    numObjects,_ := latest.Count()
    return adminBase.Render("admin/post-list.mustache", dict{
        "Posts": posts, "Pagination": paginator.Render(numObjects),
        "Unpublished": true})

}

func postAdd(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    return adminBase.Render("admin/posts-edit.mustache", ctx.Params,
        dict{"Published": 0, "IsPublished": false})
}

func postAddPost(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    post := new(db.Post)
    post.FromParams(ctx.Params)
    post.Update()
    ctx.Redirect(302, "/admin/")
    return ""
    //ctx.Redirect(302, "/admin/posts/edit/" + post.Slug + "/")
}

func postPreview(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    var post = new(db.Post)
    post.FromParams(ctx.Params)
    /* not sure the ettiquite here, RenderPost is defined in app.go */
    return RenderPost(post)
}

func postDelete(ctx *web.Context, slug string) string {
    if requireAuthentication(ctx) { return "" }
    db.Posts().C.Remove(dict{"slug": slug})
    referer := ctx.Request.Header.Get("referer")
    if len(referer) == 0 {
        referer = "/admin/"
    }
    ctx.Redirect(302, referer)
    return ""
}

func pageAdd(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    ctx.Params["Url"] = strings.TrimLeft(ctx.Params["Url"], "/")
    return adminBase.Render("admin/pages-edit.mustache", ctx.Params)
}

func pageAddPost(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    var page = new(db.Page)
    page.FromParams(ctx.Params)
    page.Update()
    ctx.Redirect(302, "/admin/")
    return ""
    //ctx.Redirect(302, "/admin/posts/edit/" + post.Slug + "/")
}

func pageEdit(ctx *web.Context, url string) string {
    if requireAuthentication(ctx) { return "" }
    var page *db.Page
    err := db.Pages().C.Find(dict{"url": url}).One(&page)
    if err != nil {
        fmt.Println(err)
        ctx.Redirect(302, "/admin/")
        return ""
    }
    if len(ctx.Params) > 1 {
        page.FromParams(ctx.Params)
        page.Update()
    }
    return adminBase.Render("admin/pages-edit.mustache", page)
}

func pagePreview(ctx *web.Context) string {
    if requireAuthentication(ctx) { return "" }
    var page = new(db.Page)
    page.FromParams(ctx.Params)
    return template.RenderMarkdown(page.Content)
}

func pageDelete(ctx *web.Context, url string) string {
    if requireAuthentication(ctx) { return "" }
    db.Pages().C.Remove(dict{"url": url})
    referer := ctx.Request.Header.Get("referer")
    if len(referer) == 0 {
        referer = "/admin/"
    }
    ctx.Redirect(302, referer)
    return ""
}

func pageList(ctx *web.Context, page string) string {
    if requireAuthentication(ctx) { return "" }
    pageNum := 1
    if len(page) != 0 { pageNum,_ = strconv.Atoi(page) }

    n := listPageSize
    paginator := NewPaginator(pageNum, n)
    paginator.Link = "/admin/pages/"
    cursor := db.Pages().C
    sort := dict{"url":1}

    var pages []db.Page
    // do a search, if required, of title and content
    var err error
    var numObjects int

    if len(ctx.Params["Search"]) > 0 {
        term := dict{"$regex": ctx.Params["Search"]}
        search := dict{"$or": []dict{dict{"url":term}, dict{"content":term}}}
        err = cursor.Find(search).Sort(sort).Skip(paginator.Skip).Limit(n).All(&pages)
        numObjects,_ = cursor.Find(search).Count()
    } else {
        err = cursor.Find(nil).Sort(sort).Skip(paginator.Skip).Limit(n).Iter().All(&pages)
        numObjects,_ = cursor.Count()
    }

    if err != nil {
        fmt.Println(err)
    }

    return adminBase.Render("admin/page-list.mustache", dict{
        "Pages": pages, "Pagination": paginator.Render(numObjects)})
}

<|endoftext|>


<commit_before>package build

import (
	"fmt"
	"neon/util"
	"reflect"
	"strings"
)

// character for expressions
const (
	// character that start expressions
	CHAR_EXPRESSION = "="
	// expression curly brace
	CURLY_EXPRESSION = "{"
	// tag separator
	TAG_SEPARATOR = " "
	// field might not be provided
	FIELD_OPTIONAL = "optional"
	// field is a file name that is expanded for user home
	FIELD_FILE = "file"
	// field is an expression
	FIELD_EXPRESSION = "expression"
	// field should be rapped in a slice of its type
	FIELD_WRAP = "wrap"
	// field is a list of steps
	FIELD_STEPS = "steps"
	// field has a different name
	FIELD_NAME = "name"
)

// Map that gives constructor for given task name
var TaskMap = make(map[string]TaskDesc)

// AddTask adds a task in the map:
// - task: description of the task
func AddTask(task TaskDesc) {
	if _, ok := TaskMap[task.Name]; ok {
		panic(fmt.Errorf("task '%s' already defined", task.Name))
	}
	TaskMap[task.Name] = task
}

// A task descriptor is made of a task constructor and an help string
type TaskDesc struct {
	Name string
	Args reflect.Type
	Func TaskFunc
	Help string
}

// Type for task arguments as parsed in build file
type TaskArgs map[interface{}]interface{}

// Type for task function called to run task
type TaskFunc func(ctx *Context, args interface{}) error

// Validate task arguments against task arguments definition
// - args: task arguments parsed in build file
// - typ: type of the arguments
// Return: an error (detailing the fault) if arguments are illegal
func ValidateTaskArgs(args TaskArgs, typ reflect.Type) error {
	if typ.Kind() != reflect.Struct {
		return fmt.Errorf("params must be a pointer on a struct")
	}
	var fields []string
	// iterate on fields of the parameters types and check argument types
	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)
		name := strings.ToLower(field.Name)
		if field.Tag.Get(FIELD_NAME) != "" {
			name = field.Tag.Get(FIELD_NAME)
		}
		fields = append(fields, name)
		// check field is not missing
		if _, ok := args[name]; !ok {
			if !FieldIs(field, FIELD_OPTIONAL) {
				return fmt.Errorf("missing mandatory field '%s'", name)
			}
		}
		value := args[name]
		// parse steps fields
		if FieldIs(field, "steps") && value != nil {
			steps, err := NewSteps(value)
			if err != nil {
				return fmt.Errorf("parsing field '%s': %v", name, err)
			}
			args[name] = steps
		}
		// check field type
		if !CheckType(field, value) {
			return fmt.Errorf("field '%s' must be of type '%s' ('%s' provided)",
				name, field.Type, reflect.TypeOf(value))
		}
	}
	// check that we don't have unknown args
	if !(typ.NumField() == 0 && len(args) == 1) {
		for name := range args {
			found := false
			for _, n := range fields {
				if n == name {
					found = true
					continue
				}
			}
			if !found {
				return fmt.Errorf("unknown parameter '%s'", name)
			}
		}
	}
	return nil
}

// CheckType checks that given value is compatible with field type
// - field: the field of the parameters as reflect.StructField
// - value: the value of the argument
// Return: a bool that tells if type is OK
func CheckType(field reflect.StructField, value interface{}) bool {
	valueType := reflect.TypeOf(value)
	// if field is optional and argument nil, it's OK
	if FieldIs(field, FIELD_OPTIONAL) && value == nil {
		return true
	}
	// if argument is an expression it's OK whatever the type
	if valueType.Kind() == reflect.String &&
		(IsExpression(value.(string)) ||
			FieldIs(field, FIELD_EXPRESSION)) {
		return true
	}
	// if type of field is slice of the type of the argument and wrap, it's OK
	if field.Type.Kind() == reflect.Slice &&
		reflect.SliceOf(valueType) == field.Type &&
		FieldIs(field, FIELD_WRAP) {
		return true
	}
	// if type is slice and argument is steps, it's OK
	if field.Type.Kind() == reflect.Slice &&
		FieldIs(field, FIELD_STEPS) {
		return true
	}
	// check that value is of given type
	return IsValueOfType(value, field.Type)
}

// IsValueOfType tells if a value is of given type
// - value: the value to test as an interface{}
// - type: the type to check as a reflect.Type
// Return: a bool telling if value is of given type
func IsValueOfType(value interface{}, typ reflect.Type) bool {
	// if value is of given type it's true
	if reflect.TypeOf(value) == typ {
		return true
	}
	// if value and type are slices, test elements
	if reflect.TypeOf(value).Kind() == reflect.Slice && typ.Kind() == reflect.Slice {
		return IsValueOfType(reflect.ValueOf(value).Index(0).Interface(), typ.Elem())
	}
	// if value and type are maps, test key and value
	if reflect.TypeOf(value).Kind() == reflect.Map && typ.Kind() == reflect.Map {
		key := reflect.ValueOf(value).MapKeys()[0].Interface()
		val := reflect.ValueOf(value).MapIndex(reflect.ValueOf(key)).Interface()
		return IsValueOfType(key, typ.Key()) && IsValueOfType(val, typ.Elem())
	}
	// else return false
	return false
}

// Build task arguments from task params and return it
// - args: task arguments parsed in build file
// - typ: the type of the arguments
// - context: the build context to evaluate arguments into
// Return:
// - result: as an interface{}
// - error: if something went wrong
func EvaluateTaskArgs(args TaskArgs, typ reflect.Type, context *Context) (interface{}, error) {
	var err error
	value := reflect.New(typ).Elem()
	for i := 0; i < value.NumField(); i++ {
		name := strings.ToLower(typ.Field(i).Name)
		field := typ.Field(i)
		if field.Tag.Get(FIELD_NAME) != "" {
			name = field.Tag.Get(FIELD_NAME)
		}
		if args[name] != nil {
			val := args[name]
			// evaluate expressions in context
			if reflect.TypeOf(val).Kind() == reflect.String &&
				(IsExpression(val.(string)) || FieldIs(field, FIELD_EXPRESSION)) {
				str := val.(string)
				if IsExpression(str) {
					str = str[1:]
				}
				val, err = context.EvaluateExpression(str)
				if err != nil {
					return nil, err
				}
				expected := field.Type
				actual := reflect.TypeOf(val)
				if actual != expected {
					return nil, fmt.Errorf("bad expression return type, expected '%s' but '%s' was returned",
						expected.Name(), actual.Name())
				}
			}
			// evaluate arguments
			val, err = context.EvaluateObject(val)
			if err != nil {
				return nil, err
			}
			// evaluate strings to replace "={expression}" with its value
			if reflect.TypeOf(val).Kind() == reflect.String {
				str := val.(string)
				// replace '\=' with '='
				if strings.HasPrefix(str, `\`+CHAR_EXPRESSION) {
					str = str[1:]
				}
				// expand home if field tagged 'file'
				if FieldIs(field, FIELD_FILE) {
					str = util.ExpandUserHome(str)
				}
				val = str
			}
			// wrap values if necessary
			if FieldIs(field, FIELD_WRAP) && !(reflect.TypeOf(val).Kind() == reflect.Slice) {
				slice := reflect.New(field.Type).Elem()
				slice = reflect.Append(slice, reflect.ValueOf(val))
				val = slice.Interface()
			}
			// put value in params
			CopyValue(reflect.ValueOf(val), value.Field(i))
		}
	}
	return value.Interface(), nil
}

// CopyValue copy given avlue in another
// - orig: origin value
// - dest: destination value
func CopyValue(orig, dest reflect.Value) {
	// loop on slices
	if orig.Type().Kind() == reflect.Slice && dest.Type().Kind() == reflect.Slice {
		new := reflect.MakeSlice(dest.Type(), orig.Len(), orig.Len())
		for i := 0; i < orig.Len(); i++ {
			CopyValue(orig.Index(i), new.Index(i))
		}
		dest.Set(new)
	} else
	// loop on maps
	if orig.Type().Kind() == reflect.Map && dest.Type().Kind() == reflect.Map {
		keyType := dest.Type().Key()
		valType := dest.Type().Elem()
		new := reflect.MakeMap(reflect.MapOf(keyType, valType))
		for _, key := range orig.MapKeys() {
			if key.Type().Kind() == reflect.Interface {
				key = key.Elem()
			}
			val := orig.MapIndex(key)
			if val.Type().Kind() == reflect.Interface {
				val = val.Elem()
			}
			new.SetMapIndex(key, val)
		}
		dest.Set(new)
	} else
	// get value of interfaces
	if orig.Kind() == reflect.Interface {
		CopyValue(orig.Elem(), dest)
	} else
	// other types
	{
		dest.Set(orig)
	}
}

// FieldIs tells if given field tag contains quality
// - field: the struct field
// - quality: the tested quality (such as "optional")
func FieldIs(field reflect.StructField, quality string) bool {
	tag := string(field.Tag)
	qualities := strings.Split(tag, TAG_SEPARATOR)
	for _, q := range qualities {
		if q == quality {
			return true
		}
	}
	return false
}

// IsExpression tells if given string is an expression
// - s: the string to test
// Return: a bool that tells if the string is an expression
func IsExpression(s string) bool {
	return s[0:1] == CHAR_EXPRESSION && s[1:2] != CURLY_EXPRESSION
}
<commit_msg>Foxed error message<commit_after>package build

import (
	"fmt"
	"neon/util"
	"reflect"
	"strings"
)

// character for expressions
const (
	// character that start expressions
	CHAR_EXPRESSION = "="
	// expression curly brace
	CURLY_EXPRESSION = "{"
	// tag separator
	TAG_SEPARATOR = " "
	// field might not be provided
	FIELD_OPTIONAL = "optional"
	// field is a file name that is expanded for user home
	FIELD_FILE = "file"
	// field is an expression
	FIELD_EXPRESSION = "expression"
	// field should be rapped in a slice of its type
	FIELD_WRAP = "wrap"
	// field is a list of steps
	FIELD_STEPS = "steps"
	// field has a different name
	FIELD_NAME = "name"
)

// Map that gives constructor for given task name
var TaskMap = make(map[string]TaskDesc)

// AddTask adds a task in the map:
// - task: description of the task
func AddTask(task TaskDesc) {
	if _, ok := TaskMap[task.Name]; ok {
		panic(fmt.Errorf("task '%s' already defined", task.Name))
	}
	TaskMap[task.Name] = task
}

// A task descriptor is made of a task constructor and an help string
type TaskDesc struct {
	Name string
	Args reflect.Type
	Func TaskFunc
	Help string
}

// Type for task arguments as parsed in build file
type TaskArgs map[interface{}]interface{}

// Type for task function called to run task
type TaskFunc func(ctx *Context, args interface{}) error

// Validate task arguments against task arguments definition
// - args: task arguments parsed in build file
// - typ: type of the arguments
// Return: an error (detailing the fault) if arguments are illegal
func ValidateTaskArgs(args TaskArgs, typ reflect.Type) error {
	if typ.Kind() != reflect.Struct {
		return fmt.Errorf("params must be a pointer on a struct")
	}
	var fields []string
	// iterate on fields of the parameters types and check argument types
	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)
		name := strings.ToLower(field.Name)
		if field.Tag.Get(FIELD_NAME) != "" {
			name = field.Tag.Get(FIELD_NAME)
		}
		fields = append(fields, name)
		// check field is not missing
		if _, ok := args[name]; !ok {
			if !FieldIs(field, FIELD_OPTIONAL) {
				return fmt.Errorf("missing mandatory field '%s'", name)
			}
		}
		value := args[name]
		// parse steps fields
		if FieldIs(field, "steps") && value != nil {
			steps, err := NewSteps(value)
			if err != nil {
				return fmt.Errorf("parsing field '%s': %v", name, err)
			}
			args[name] = steps
		}
		// check field type
		if !CheckType(field, value) {
			return fmt.Errorf("field '%s' must be of type '%s' ('%s' provided)",
				name, field.Type, reflect.TypeOf(value))
		}
	}
	// check that we don't have unknown args
	if !(typ.NumField() == 0 && len(args) == 1) {
		for name := range args {
			found := false
			for _, n := range fields {
				if n == name {
					found = true
					continue
				}
			}
			if !found {
				return fmt.Errorf("unknown parameter '%s'", name)
			}
		}
	}
	return nil
}

// CheckType checks that given value is compatible with field type
// - field: the field of the parameters as reflect.StructField
// - value: the value of the argument
// Return: a bool that tells if type is OK
func CheckType(field reflect.StructField, value interface{}) bool {
	valueType := reflect.TypeOf(value)
	// if field is optional and argument nil, it's OK
	if FieldIs(field, FIELD_OPTIONAL) && value == nil {
		return true
	}
	// if argument is an expression it's OK whatever the type
	if valueType.Kind() == reflect.String &&
		(IsExpression(value.(string)) ||
			FieldIs(field, FIELD_EXPRESSION)) {
		return true
	}
	// if type of field is slice of the type of the argument and wrap, it's OK
	if field.Type.Kind() == reflect.Slice &&
		reflect.SliceOf(valueType) == field.Type &&
		FieldIs(field, FIELD_WRAP) {
		return true
	}
	// if type is slice and argument is steps, it's OK
	if field.Type.Kind() == reflect.Slice &&
		FieldIs(field, FIELD_STEPS) {
		return true
	}
	// check that value is of given type
	return IsValueOfType(value, field.Type)
}

// IsValueOfType tells if a value is of given type
// - value: the value to test as an interface{}
// - type: the type to check as a reflect.Type
// Return: a bool telling if value is of given type
func IsValueOfType(value interface{}, typ reflect.Type) bool {
	// if value is of given type it's true
	if reflect.TypeOf(value) == typ {
		return true
	}
	// if value and type are slices, test elements
	if reflect.TypeOf(value).Kind() == reflect.Slice && typ.Kind() == reflect.Slice {
		return IsValueOfType(reflect.ValueOf(value).Index(0).Interface(), typ.Elem())
	}
	// if value and type are maps, test key and value
	if reflect.TypeOf(value).Kind() == reflect.Map && typ.Kind() == reflect.Map {
		key := reflect.ValueOf(value).MapKeys()[0].Interface()
		val := reflect.ValueOf(value).MapIndex(reflect.ValueOf(key)).Interface()
		return IsValueOfType(key, typ.Key()) && IsValueOfType(val, typ.Elem())
	}
	// else return false
	return false
}

// Build task arguments from task params and return it
// - args: task arguments parsed in build file
// - typ: the type of the arguments
// - context: the build context to evaluate arguments into
// Return:
// - result: as an interface{}
// - error: if something went wrong
func EvaluateTaskArgs(args TaskArgs, typ reflect.Type, context *Context) (interface{}, error) {
	var err error
	value := reflect.New(typ).Elem()
	for i := 0; i < value.NumField(); i++ {
		name := strings.ToLower(typ.Field(i).Name)
		field := typ.Field(i)
		if field.Tag.Get(FIELD_NAME) != "" {
			name = field.Tag.Get(FIELD_NAME)
		}
		if args[name] != nil {
			val := args[name]
			// evaluate expressions in context
			if reflect.TypeOf(val).Kind() == reflect.String &&
				(IsExpression(val.(string)) || FieldIs(field, FIELD_EXPRESSION)) {
				str := val.(string)
				if IsExpression(str) {
					str = str[1:]
				}
				val, err = context.EvaluateExpression(str)
				if err != nil {
					return nil, err
				}
				expected := field.Type
				actual := reflect.TypeOf(val)
				if actual != expected {
					return nil, fmt.Errorf("bad expression return type, expected '%v' but '%v' was returned",
						expected, actual)
				}
			}
			// evaluate arguments
			val, err = context.EvaluateObject(val)
			if err != nil {
				return nil, err
			}
			// evaluate strings to replace "={expression}" with its value
			if reflect.TypeOf(val).Kind() == reflect.String {
				str := val.(string)
				// replace '\=' with '='
				if strings.HasPrefix(str, `\`+CHAR_EXPRESSION) {
					str = str[1:]
				}
				// expand home if field tagged 'file'
				if FieldIs(field, FIELD_FILE) {
					str = util.ExpandUserHome(str)
				}
				val = str
			}
			// wrap values if necessary
			if FieldIs(field, FIELD_WRAP) && !(reflect.TypeOf(val).Kind() == reflect.Slice) {
				slice := reflect.New(field.Type).Elem()
				slice = reflect.Append(slice, reflect.ValueOf(val))
				val = slice.Interface()
			}
			// put value in params
			CopyValue(reflect.ValueOf(val), value.Field(i))
		}
	}
	return value.Interface(), nil
}

// CopyValue copy given avlue in another
// - orig: origin value
// - dest: destination value
func CopyValue(orig, dest reflect.Value) {
	// loop on slices
	if orig.Type().Kind() == reflect.Slice && dest.Type().Kind() == reflect.Slice {
		new := reflect.MakeSlice(dest.Type(), orig.Len(), orig.Len())
		for i := 0; i < orig.Len(); i++ {
			CopyValue(orig.Index(i), new.Index(i))
		}
		dest.Set(new)
	} else
	// loop on maps
	if orig.Type().Kind() == reflect.Map && dest.Type().Kind() == reflect.Map {
		keyType := dest.Type().Key()
		valType := dest.Type().Elem()
		new := reflect.MakeMap(reflect.MapOf(keyType, valType))
		for _, key := range orig.MapKeys() {
			if key.Type().Kind() == reflect.Interface {
				key = key.Elem()
			}
			val := orig.MapIndex(key)
			if val.Type().Kind() == reflect.Interface {
				val = val.Elem()
			}
			new.SetMapIndex(key, val)
		}
		dest.Set(new)
	} else
	// get value of interfaces
	if orig.Kind() == reflect.Interface {
		CopyValue(orig.Elem(), dest)
	} else
	// other types
	{
		dest.Set(orig)
	}
}

// FieldIs tells if given field tag contains quality
// - field: the struct field
// - quality: the tested quality (such as "optional")
func FieldIs(field reflect.StructField, quality string) bool {
	tag := string(field.Tag)
	qualities := strings.Split(tag, TAG_SEPARATOR)
	for _, q := range qualities {
		if q == quality {
			return true
		}
	}
	return false
}

// IsExpression tells if given string is an expression
// - s: the string to test
// Return: a bool that tells if the string is an expression
func IsExpression(s string) bool {
	return s[0:1] == CHAR_EXPRESSION && s[1:2] != CURLY_EXPRESSION
}
<|endoftext|>


<commit_before>package parser

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strings"
)

//define address
const (
	Xunlei   = "http://bt.box.n0808.com/%s/%s/%s.torrent"
	Torcache = "https://torcache.net/torrent/%s.torrent"
)

//define errors
var (
	ErrNotFound = errors.New("not found")
	LibUrls     = []string{
		"http://www.torrent.org.cn/Home/torrent/download.html?hash=%s",
		"http://torcache.net/torrent/%s.torrent",
		"http://torrage.com/torrent/%s.torrent",
		"http://zoink.it/torrent/%s.torrent",
		"https://178.73.198.210/torrent/%s.torrent",
		"http://d1.torrentkittycn.com/?infohash=%s",
		"http://reflektor.karmorra.info/torrent/%s.torrent",
	}
)

//DownloadXunlei torrent
func DownloadXunlei(hash string, client *http.Client) (mi MetaInfo, err error) {
	mi.InfoHash = hash
	if len(hash) != 40 {
		err = errors.New("invalid hash len")
		return
	}

	//从迅雷种子库查找
	address := fmt.Sprintf(Xunlei, hash[:2], hash[len(hash)-2:], hash)
	req0, err := http.NewRequest("GET", address, nil)
	if err != nil {
		return
	}
	req0.Header.Set("User-Agent", "Mozilla/5.0")
	resp, err := client.Do(req0)
	if err != nil {
		return
	}
	if resp != nil {
		defer func() {
			// io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}()

		if resp.StatusCode == 200 {
			//解析种子
			err = mi.Parse(resp.Body)
		} else if resp.StatusCode == 404 {
			err = ErrNotFound
		} else {
			err = errors.New("refuse error")
		}
	}
	return
}

//Download torrent
func DownloadTorrent(hash string, client *http.Client) (mi MetaInfo, err error) {
	if len(hash) != 40 {
		err = errors.New("invalid hash len")
		return
	}
	mi, err = DownloadXunlei(hash, client)
	//迅雷解析成功，不用再調用後面的種子庫
	if err == nil {
		return
	}

	mi.InfoHash = hash
	//將來改用字典實現
	for _, lib_url := range LibUrls {
		address := fmt.Sprintf(lib_url, strings.ToUpper(hash))
		req0, err := http.NewRequest("GET", address, nil)
		if err != nil {
			continue
		}
		resp, err := client.Do(req0)
		if err != nil {
			continue
		}
		if resp != nil {
			defer func() {
				// io.Copy(ioutil.Discard, resp.Body)
				resp.Body.Close()
			}()

			if resp.StatusCode == 200 {
				//解析种子
				err = mi.Parse(resp.Body)
				return
			} else if resp.StatusCode == 404 {
				err = ErrNotFound
			} else {
				err = errors.New("refuse error")
			}
		}
	}
	return
}

func pretty(v interface{}) {
	b, _ := json.MarshalIndent(v, " ", "  ")
	fmt.Println(string(b))
}
<commit_msg>fix return  shadowed during return<commit_after>package parser

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strings"
)

//define address
const (
	Xunlei   = "http://bt.box.n0808.com/%s/%s/%s.torrent"
	Torcache = "https://torcache.net/torrent/%s.torrent"
)

//define errors
var (
	ErrNotFound = errors.New("not found")
	LibUrls     = []string{
		"http://www.torrent.org.cn/Home/torrent/download.html?hash=%s",
		"http://torcache.net/torrent/%s.torrent",
		"http://torrage.com/torrent/%s.torrent",
		"http://zoink.it/torrent/%s.torrent",
		"https://178.73.198.210/torrent/%s.torrent",
		"http://d1.torrentkittycn.com/?infohash=%s",
		"http://reflektor.karmorra.info/torrent/%s.torrent",
	}
)

//DownloadXunlei torrent
func DownloadXunlei(hash string, client *http.Client) (mi MetaInfo, err error) {
	mi.InfoHash = hash
	if len(hash) != 40 {
		err = errors.New("invalid hash len")
		return
	}

	//从迅雷种子库查找
	address := fmt.Sprintf(Xunlei, hash[:2], hash[len(hash)-2:], hash)
	req0, err := http.NewRequest("GET", address, nil)
	if err != nil {
		return
	}
	req0.Header.Set("User-Agent", "Mozilla/5.0")
	resp, err := client.Do(req0)
	if err != nil {
		return
	}
	if resp != nil {
		defer func() {
			// io.Copy(ioutil.Discard, resp.Body)
			resp.Body.Close()
		}()

		if resp.StatusCode == 200 {
			//解析种子
			err = mi.Parse(resp.Body)
		} else if resp.StatusCode == 404 {
			err = ErrNotFound
		} else {
			err = errors.New("refuse error")
		}
	}
	return
}

//Download torrent
func DownloadTorrent(hash string, client *http.Client) (mi MetaInfo, err error) {
	if len(hash) != 40 {
		err = errors.New("invalid hash len")
		return
	}
	mi, err = DownloadXunlei(hash, client)
	//迅雷解析成功，不用再調用後面的種子庫
	if err == nil {
		return
	}

	mi.InfoHash = hash
	//將來改用字典實現
	for _, lib_url := range LibUrls {
		address := fmt.Sprintf(lib_url, strings.ToUpper(hash))
		req0, err := http.NewRequest("GET", address, nil)
		if err != nil {
			continue
		}
		resp, err := client.Do(req0)
		if err != nil {
			continue
		}
		if resp != nil {
			defer func() {
				// io.Copy(ioutil.Discard, resp.Body)
				resp.Body.Close()
			}()

			if resp.StatusCode == 200 {
				//解析种子
				err = mi.Parse(resp.Body)
				return mi, err
			} else if resp.StatusCode == 404 {
				err = ErrNotFound
			} else {
				err = errors.New("refuse error")
			}
		}
	}
	return
}

func pretty(v interface{}) {
	b, _ := json.MarshalIndent(v, " ", "  ")
	fmt.Println(string(b))
}
<|endoftext|>


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

package os

import (
	"internal/poll"
	"internal/syscall/windows"
	"runtime"
	"syscall"
	"unicode/utf16"
	"unsafe"
)

// file is the real representation of *File.
// The extra level of indirection ensures that no clients of os
// can overwrite this data, which could cause the finalizer
// to close the wrong file descriptor.
type file struct {
	pfd     poll.FD
	name    string
	dirinfo *dirInfo // nil unless directory being read
}

// Fd returns the Windows handle referencing the open file.
// The handle is valid only until f.Close is called or f is garbage collected.
// On Unix systems this will cause the SetDeadline methods to stop working.
func (file *File) Fd() uintptr {
	if file == nil {
		return uintptr(syscall.InvalidHandle)
	}
	return uintptr(file.pfd.Sysfd)
}

// newFile returns a new File with the given file handle and name.
// Unlike NewFile, it does not check that h is syscall.InvalidHandle.
func newFile(h syscall.Handle, name string, kind string) *File {
	if kind == "file" {
		var m uint32
		if syscall.GetConsoleMode(h, &m) == nil {
			kind = "console"
		}
	}

	f := &File{&file{
		pfd: poll.FD{
			Sysfd:         h,
			IsStream:      true,
			ZeroReadIsEOF: true,
		},
		name: name,
	}}
	runtime.SetFinalizer(f.file, (*file).close)

	// Ignore initialization errors.
	// Assume any problems will show up in later I/O.
	f.pfd.Init(kind, false)

	return f
}

// newConsoleFile creates new File that will be used as console.
func newConsoleFile(h syscall.Handle, name string) *File {
	return newFile(h, name, "console")
}

// NewFile returns a new File with the given file descriptor and
// name. The returned value will be nil if fd is not a valid file
// descriptor.
func NewFile(fd uintptr, name string) *File {
	h := syscall.Handle(fd)
	if h == syscall.InvalidHandle {
		return nil
	}
	return newFile(h, name, "file")
}

// Auxiliary information if the File describes a directory
type dirInfo struct {
	data     syscall.Win32finddata
	needdata bool
	path     string
	isempty  bool // set if FindFirstFile returns ERROR_FILE_NOT_FOUND
}

func epipecheck(file *File, e error) {
}

const DevNull = "NUL"

func (f *file) isdir() bool { return f != nil && f.dirinfo != nil }

func openFile(name string, flag int, perm FileMode) (file *File, err error) {
	r, e := syscall.Open(fixLongPath(name), flag|syscall.O_CLOEXEC, syscallMode(perm))
	if e != nil {
		return nil, e
	}
	return newFile(r, name, "file"), nil
}

func openDir(name string) (file *File, err error) {
	var mask string

	path := fixLongPath(name)

	if len(path) == 2 && path[1] == ':' || (len(path) > 0 && path[len(path)-1] == '\\') { // it is a drive letter, like C:
		mask = path + `*`
	} else {
		mask = path + `\*`
	}
	maskp, e := syscall.UTF16PtrFromString(mask)
	if e != nil {
		return nil, e
	}
	d := new(dirInfo)
	r, e := syscall.FindFirstFile(maskp, &d.data)
	if e != nil {
		// FindFirstFile returns ERROR_FILE_NOT_FOUND when
		// no matching files can be found. Then, if directory
		// exists, we should proceed.
		if e != syscall.ERROR_FILE_NOT_FOUND {
			return nil, e
		}
		var fa syscall.Win32FileAttributeData
		pathp, e := syscall.UTF16PtrFromString(path)
		if e != nil {
			return nil, e
		}
		e = syscall.GetFileAttributesEx(pathp, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fa)))
		if e != nil {
			return nil, e
		}
		if fa.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY == 0 {
			return nil, e
		}
		d.isempty = true
	}
	d.path = path
	if !isAbs(d.path) {
		d.path, e = syscall.FullPath(d.path)
		if e != nil {
			return nil, e
		}
	}
	f := newFile(r, name, "dir")
	f.dirinfo = d
	return f, nil
}

// openFileNolog is the Windows implementation of OpenFile.
func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
	if name == "" {
		return nil, &PathError{"open", name, syscall.ENOENT}
	}
	r, errf := openFile(name, flag, perm)
	if errf == nil {
		return r, nil
	}
	r, errd := openDir(name)
	if errd == nil {
		if flag&O_WRONLY != 0 || flag&O_RDWR != 0 {
			r.Close()
			return nil, &PathError{"open", name, syscall.EISDIR}
		}
		return r, nil
	}
	return nil, &PathError{"open", name, errf}
}

// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (file *File) Close() error {
	if file == nil {
		return ErrInvalid
	}
	return file.file.close()
}

func (file *file) close() error {
	if file == nil {
		return syscall.EINVAL
	}
	if file.isdir() && file.dirinfo.isempty {
		// "special" empty directories
		return nil
	}
	var err error
	if e := file.pfd.Close(); e != nil {
		if e == poll.ErrFileClosing {
			e = ErrClosed
		}
		err = &PathError{"close", file.name, e}
	}

	// no need for a finalizer anymore
	runtime.SetFinalizer(file, nil)
	return err
}

// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func (f *File) read(b []byte) (n int, err error) {
	n, err = f.pfd.Read(b)
	runtime.KeepAlive(f)
	return n, err
}

// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to 0.
func (f *File) pread(b []byte, off int64) (n int, err error) {
	n, err = f.pfd.Pread(b, off)
	runtime.KeepAlive(f)
	return n, err
}

// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func (f *File) write(b []byte) (n int, err error) {
	n, err = f.pfd.Write(b)
	runtime.KeepAlive(f)
	return n, err
}

// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func (f *File) pwrite(b []byte, off int64) (n int, err error) {
	n, err = f.pfd.Pwrite(b, off)
	runtime.KeepAlive(f)
	return n, err
}

// seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func (f *File) seek(offset int64, whence int) (ret int64, err error) {
	ret, err = f.pfd.Seek(offset, whence)
	runtime.KeepAlive(f)
	return ret, err
}

// Truncate changes the size of the named file.
// If the file is a symbolic link, it changes the size of the link's target.
func Truncate(name string, size int64) error {
	f, e := OpenFile(name, O_WRONLY|O_CREATE, 0666)
	if e != nil {
		return e
	}
	defer f.Close()
	e1 := f.Truncate(size)
	if e1 != nil {
		return e1
	}
	return nil
}

// Remove removes the named file or directory.
// If there is an error, it will be of type *PathError.
func Remove(name string) error {
	p, e := syscall.UTF16PtrFromString(fixLongPath(name))
	if e != nil {
		return &PathError{"remove", name, e}
	}

	// Go file interface forces us to know whether
	// name is a file or directory. Try both.
	e = syscall.DeleteFile(p)
	if e == nil {
		return nil
	}
	e1 := syscall.RemoveDirectory(p)
	if e1 == nil {
		return nil
	}

	// Both failed: figure out which error to return.
	if e1 != e {
		a, e2 := syscall.GetFileAttributes(p)
		if e2 != nil {
			e = e2
		} else {
			if a&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
				e = e1
			} else if a&syscall.FILE_ATTRIBUTE_READONLY != 0 {
				if e1 = syscall.SetFileAttributes(p, a&^syscall.FILE_ATTRIBUTE_READONLY); e1 == nil {
					if e = syscall.DeleteFile(p); e == nil {
						return nil
					}
				}
			}
		}
	}
	return &PathError{"remove", name, e}
}

func rename(oldname, newname string) error {
	e := windows.Rename(fixLongPath(oldname), fixLongPath(newname))
	if e != nil {
		return &LinkError{"rename", oldname, newname, e}
	}
	return nil
}

// Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an error, if any.
func Pipe() (r *File, w *File, err error) {
	var p [2]syscall.Handle
	e := syscall.CreatePipe(&p[0], &p[1], nil, 0)
	if e != nil {
		return nil, nil, NewSyscallError("pipe", e)
	}
	return newFile(p[0], "|0", "file"), newFile(p[1], "|1", "file"), nil
}

func tempDir() string {
	n := uint32(syscall.MAX_PATH)
	for {
		b := make([]uint16, n)
		n, _ = syscall.GetTempPath(uint32(len(b)), &b[0])
		if n > uint32(len(b)) {
			continue
		}
		if n > 0 && b[n-1] == '\\' {
			n--
		}
		return string(utf16.Decode(b[:n]))
	}
}

// Link creates newname as a hard link to the oldname file.
// If there is an error, it will be of type *LinkError.
func Link(oldname, newname string) error {
	n, err := syscall.UTF16PtrFromString(fixLongPath(newname))
	if err != nil {
		return &LinkError{"link", oldname, newname, err}
	}
	o, err := syscall.UTF16PtrFromString(fixLongPath(oldname))
	if err != nil {
		return &LinkError{"link", oldname, newname, err}
	}
	err = syscall.CreateHardLink(n, o, 0)
	if err != nil {
		return &LinkError{"link", oldname, newname, err}
	}
	return nil
}

// Symlink creates newname as a symbolic link to oldname.
// If there is an error, it will be of type *LinkError.
func Symlink(oldname, newname string) error {
	// '/' does not work in link's content
	oldname = fromSlash(oldname)

	// need the exact location of the oldname when its relative to determine if its a directory
	destpath := oldname
	if !isAbs(oldname) {
		destpath = dirname(newname) + `\` + oldname
	}

	fi, err := Lstat(destpath)
	isdir := err == nil && fi.IsDir()

	n, err := syscall.UTF16PtrFromString(fixLongPath(newname))
	if err != nil {
		return &LinkError{"symlink", oldname, newname, err}
	}
	o, err := syscall.UTF16PtrFromString(fixLongPath(oldname))
	if err != nil {
		return &LinkError{"symlink", oldname, newname, err}
	}

	var flags uint32
	if isdir {
		flags |= syscall.SYMBOLIC_LINK_FLAG_DIRECTORY
	}
	err = syscall.CreateSymbolicLink(n, o, flags)
	if err != nil {
		return &LinkError{"symlink", oldname, newname, err}
	}
	return nil
}
<commit_msg>os: document DevNull on windows<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package os

import (
	"internal/poll"
	"internal/syscall/windows"
	"runtime"
	"syscall"
	"unicode/utf16"
	"unsafe"
)

// file is the real representation of *File.
// The extra level of indirection ensures that no clients of os
// can overwrite this data, which could cause the finalizer
// to close the wrong file descriptor.
type file struct {
	pfd     poll.FD
	name    string
	dirinfo *dirInfo // nil unless directory being read
}

// Fd returns the Windows handle referencing the open file.
// The handle is valid only until f.Close is called or f is garbage collected.
// On Unix systems this will cause the SetDeadline methods to stop working.
func (file *File) Fd() uintptr {
	if file == nil {
		return uintptr(syscall.InvalidHandle)
	}
	return uintptr(file.pfd.Sysfd)
}

// newFile returns a new File with the given file handle and name.
// Unlike NewFile, it does not check that h is syscall.InvalidHandle.
func newFile(h syscall.Handle, name string, kind string) *File {
	if kind == "file" {
		var m uint32
		if syscall.GetConsoleMode(h, &m) == nil {
			kind = "console"
		}
	}

	f := &File{&file{
		pfd: poll.FD{
			Sysfd:         h,
			IsStream:      true,
			ZeroReadIsEOF: true,
		},
		name: name,
	}}
	runtime.SetFinalizer(f.file, (*file).close)

	// Ignore initialization errors.
	// Assume any problems will show up in later I/O.
	f.pfd.Init(kind, false)

	return f
}

// newConsoleFile creates new File that will be used as console.
func newConsoleFile(h syscall.Handle, name string) *File {
	return newFile(h, name, "console")
}

// NewFile returns a new File with the given file descriptor and
// name. The returned value will be nil if fd is not a valid file
// descriptor.
func NewFile(fd uintptr, name string) *File {
	h := syscall.Handle(fd)
	if h == syscall.InvalidHandle {
		return nil
	}
	return newFile(h, name, "file")
}

// Auxiliary information if the File describes a directory
type dirInfo struct {
	data     syscall.Win32finddata
	needdata bool
	path     string
	isempty  bool // set if FindFirstFile returns ERROR_FILE_NOT_FOUND
}

func epipecheck(file *File, e error) {
}

// DevNull is the name of the operating system's ``null device.''
// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
const DevNull = "NUL"

func (f *file) isdir() bool { return f != nil && f.dirinfo != nil }

func openFile(name string, flag int, perm FileMode) (file *File, err error) {
	r, e := syscall.Open(fixLongPath(name), flag|syscall.O_CLOEXEC, syscallMode(perm))
	if e != nil {
		return nil, e
	}
	return newFile(r, name, "file"), nil
}

func openDir(name string) (file *File, err error) {
	var mask string

	path := fixLongPath(name)

	if len(path) == 2 && path[1] == ':' || (len(path) > 0 && path[len(path)-1] == '\\') { // it is a drive letter, like C:
		mask = path + `*`
	} else {
		mask = path + `\*`
	}
	maskp, e := syscall.UTF16PtrFromString(mask)
	if e != nil {
		return nil, e
	}
	d := new(dirInfo)
	r, e := syscall.FindFirstFile(maskp, &d.data)
	if e != nil {
		// FindFirstFile returns ERROR_FILE_NOT_FOUND when
		// no matching files can be found. Then, if directory
		// exists, we should proceed.
		if e != syscall.ERROR_FILE_NOT_FOUND {
			return nil, e
		}
		var fa syscall.Win32FileAttributeData
		pathp, e := syscall.UTF16PtrFromString(path)
		if e != nil {
			return nil, e
		}
		e = syscall.GetFileAttributesEx(pathp, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fa)))
		if e != nil {
			return nil, e
		}
		if fa.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY == 0 {
			return nil, e
		}
		d.isempty = true
	}
	d.path = path
	if !isAbs(d.path) {
		d.path, e = syscall.FullPath(d.path)
		if e != nil {
			return nil, e
		}
	}
	f := newFile(r, name, "dir")
	f.dirinfo = d
	return f, nil
}

// openFileNolog is the Windows implementation of OpenFile.
func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
	if name == "" {
		return nil, &PathError{"open", name, syscall.ENOENT}
	}
	r, errf := openFile(name, flag, perm)
	if errf == nil {
		return r, nil
	}
	r, errd := openDir(name)
	if errd == nil {
		if flag&O_WRONLY != 0 || flag&O_RDWR != 0 {
			r.Close()
			return nil, &PathError{"open", name, syscall.EISDIR}
		}
		return r, nil
	}
	return nil, &PathError{"open", name, errf}
}

// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (file *File) Close() error {
	if file == nil {
		return ErrInvalid
	}
	return file.file.close()
}

func (file *file) close() error {
	if file == nil {
		return syscall.EINVAL
	}
	if file.isdir() && file.dirinfo.isempty {
		// "special" empty directories
		return nil
	}
	var err error
	if e := file.pfd.Close(); e != nil {
		if e == poll.ErrFileClosing {
			e = ErrClosed
		}
		err = &PathError{"close", file.name, e}
	}

	// no need for a finalizer anymore
	runtime.SetFinalizer(file, nil)
	return err
}

// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func (f *File) read(b []byte) (n int, err error) {
	n, err = f.pfd.Read(b)
	runtime.KeepAlive(f)
	return n, err
}

// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to 0.
func (f *File) pread(b []byte, off int64) (n int, err error) {
	n, err = f.pfd.Pread(b, off)
	runtime.KeepAlive(f)
	return n, err
}

// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func (f *File) write(b []byte) (n int, err error) {
	n, err = f.pfd.Write(b)
	runtime.KeepAlive(f)
	return n, err
}

// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func (f *File) pwrite(b []byte, off int64) (n int, err error) {
	n, err = f.pfd.Pwrite(b, off)
	runtime.KeepAlive(f)
	return n, err
}

// seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func (f *File) seek(offset int64, whence int) (ret int64, err error) {
	ret, err = f.pfd.Seek(offset, whence)
	runtime.KeepAlive(f)
	return ret, err
}

// Truncate changes the size of the named file.
// If the file is a symbolic link, it changes the size of the link's target.
func Truncate(name string, size int64) error {
	f, e := OpenFile(name, O_WRONLY|O_CREATE, 0666)
	if e != nil {
		return e
	}
	defer f.Close()
	e1 := f.Truncate(size)
	if e1 != nil {
		return e1
	}
	return nil
}

// Remove removes the named file or directory.
// If there is an error, it will be of type *PathError.
func Remove(name string) error {
	p, e := syscall.UTF16PtrFromString(fixLongPath(name))
	if e != nil {
		return &PathError{"remove", name, e}
	}

	// Go file interface forces us to know whether
	// name is a file or directory. Try both.
	e = syscall.DeleteFile(p)
	if e == nil {
		return nil
	}
	e1 := syscall.RemoveDirectory(p)
	if e1 == nil {
		return nil
	}

	// Both failed: figure out which error to return.
	if e1 != e {
		a, e2 := syscall.GetFileAttributes(p)
		if e2 != nil {
			e = e2
		} else {
			if a&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
				e = e1
			} else if a&syscall.FILE_ATTRIBUTE_READONLY != 0 {
				if e1 = syscall.SetFileAttributes(p, a&^syscall.FILE_ATTRIBUTE_READONLY); e1 == nil {
					if e = syscall.DeleteFile(p); e == nil {
						return nil
					}
				}
			}
		}
	}
	return &PathError{"remove", name, e}
}

func rename(oldname, newname string) error {
	e := windows.Rename(fixLongPath(oldname), fixLongPath(newname))
	if e != nil {
		return &LinkError{"rename", oldname, newname, e}
	}
	return nil
}

// Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an error, if any.
func Pipe() (r *File, w *File, err error) {
	var p [2]syscall.Handle
	e := syscall.CreatePipe(&p[0], &p[1], nil, 0)
	if e != nil {
		return nil, nil, NewSyscallError("pipe", e)
	}
	return newFile(p[0], "|0", "file"), newFile(p[1], "|1", "file"), nil
}

func tempDir() string {
	n := uint32(syscall.MAX_PATH)
	for {
		b := make([]uint16, n)
		n, _ = syscall.GetTempPath(uint32(len(b)), &b[0])
		if n > uint32(len(b)) {
			continue
		}
		if n > 0 && b[n-1] == '\\' {
			n--
		}
		return string(utf16.Decode(b[:n]))
	}
}

// Link creates newname as a hard link to the oldname file.
// If there is an error, it will be of type *LinkError.
func Link(oldname, newname string) error {
	n, err := syscall.UTF16PtrFromString(fixLongPath(newname))
	if err != nil {
		return &LinkError{"link", oldname, newname, err}
	}
	o, err := syscall.UTF16PtrFromString(fixLongPath(oldname))
	if err != nil {
		return &LinkError{"link", oldname, newname, err}
	}
	err = syscall.CreateHardLink(n, o, 0)
	if err != nil {
		return &LinkError{"link", oldname, newname, err}
	}
	return nil
}

// Symlink creates newname as a symbolic link to oldname.
// If there is an error, it will be of type *LinkError.
func Symlink(oldname, newname string) error {
	// '/' does not work in link's content
	oldname = fromSlash(oldname)

	// need the exact location of the oldname when its relative to determine if its a directory
	destpath := oldname
	if !isAbs(oldname) {
		destpath = dirname(newname) + `\` + oldname
	}

	fi, err := Lstat(destpath)
	isdir := err == nil && fi.IsDir()

	n, err := syscall.UTF16PtrFromString(fixLongPath(newname))
	if err != nil {
		return &LinkError{"symlink", oldname, newname, err}
	}
	o, err := syscall.UTF16PtrFromString(fixLongPath(oldname))
	if err != nil {
		return &LinkError{"symlink", oldname, newname, err}
	}

	var flags uint32
	if isdir {
		flags |= syscall.SYMBOLIC_LINK_FLAG_DIRECTORY
	}
	err = syscall.CreateSymbolicLink(n, o, flags)
	if err != nil {
		return &LinkError{"symlink", oldname, newname, err}
	}
	return nil
}
<|endoftext|>


<commit_before>package gform

import (
    "fmt"
    "syscall"
    "unsafe"
    "unicode/utf16"
    "w32"
    "w32/user32"
    "w32/comctl32"
)

func internalTrackMouseEvent(hwnd w32.HWND) {
    var tme w32.TRACKMOUSEEVENT
    tme.CbSize = uint(unsafe.Sizeof(tme))
    tme.DwFlags = w32.TME_LEAVE
    tme.HwndTrack = hwnd
    tme.DwHoverTime = w32.HOVER_DEFAULT

    comctl32.TrackMouseEvent(&tme)
}

func UTF16PtrToString(cstr *uint16) string {
    if cstr != nil {
        us := make([]uint16, 0, 256)
        for p := uintptr(unsafe.Pointer(cstr)); ; p += 2 {
            u := *(*uint16)(unsafe.Pointer(p))
            if u == 0 {
                return string(utf16.Decode(us))
            }
            us = append(us, u)
        }
    }

    return ""
}

func ToggleStyle(hwnd w32.HWND, b bool, style int) {
    originalStyle := int(user32.GetWindowLongPtr(hwnd, w32.GWL_STYLE))
    if originalStyle != 0 {
        if b {
            originalStyle |= style
        } else {
            originalStyle ^= style
        }
        user32.SetWindowLongPtr(hwnd, w32.GWL_STYLE, uintptr(originalStyle))
    }
}

func ToggleExStyle(hwnd w32.HWND, b bool, style int) {
    originalStyle := int(user32.GetWindowLongPtr(hwnd, w32.GWL_EXSTYLE))
    if originalStyle != 0 {
        if b {
            originalStyle |= style
        } else {
            originalStyle ^= style
        }
        user32.SetWindowLongPtr(hwnd, w32.GWL_EXSTYLE, uintptr(originalStyle))
    }
}

func CreateWindow(className string, parent Controller, exStyle, style uint) w32.HWND {
    instance := GetAppInstance()
    var parentHwnd w32.HWND
    if parent != nil {
        parentHwnd = parent.Handle()
    }
    var hwnd w32.HWND
    hwnd = user32.CreateWindowEx(
        exStyle,
        syscall.StringToUTF16Ptr(className),
        nil,
        style,
        w32.CW_USEDEFAULT,
        w32.CW_USEDEFAULT,
        w32.CW_USEDEFAULT,
        w32.CW_USEDEFAULT,
        parentHwnd,
        0,
        instance,
        nil)

    if hwnd == 0 {
        errStr := fmt.Sprintf("Error occurred in CreateWindow(%s, %v, %d, %d)", className, parent, exStyle, style)
        panic(errStr)
    }

    return hwnd
}

func RegisterClass(className string, wndproc uintptr) {
    instance := GetAppInstance()
    icon := user32.LoadIcon(instance, w32.MakeIntResource(w32.IDI_APPLICATION))

    var wc w32.WNDCLASSEX
    wc.Size = uint(unsafe.Sizeof(wc))
    wc.Style = w32.CS_HREDRAW | w32.CS_VREDRAW
    wc.WndProc = wndproc
    wc.Instance = instance
    wc.Background = w32.COLOR_BTNFACE + 1
    wc.Icon = icon
    wc.Cursor = user32.LoadCursor(0, w32.MakeIntResource(w32.IDC_ARROW))
    wc.ClassName = syscall.StringToUTF16Ptr(className)
    wc.MenuName = nil
    wc.IconSm = icon

    if ret := user32.RegisterClassEx(&wc); ret == 0 {
        panic(syscall.GetLastError())
    }
}

func RegClassOnlyOnce(className string) {
    isExists := false
    for _, class := range gRegisteredClasses {
        if class == className {
            isExists = true
            break
        }
    }

    if !isExists {
        RegisterClass(className, GeneralWndprocCallBack)
        gRegisteredClasses = append(gRegisteredClasses, className)
    }
}

func ScreenToClientRect(hwnd w32.HWND, rect *w32.RECT) *Rect {
    l, t, r, b := rect.Left, rect.Top, rect.Right, rect.Bottom

    l, t = user32.ScreenToClient(hwnd, l, t)
    r, b = user32.ScreenToClient(hwnd, r, b)
    return NewRect(l, t, r, b)
}<commit_msg>Remove UTF16PtrToString.<commit_after>package gform

import (
    "fmt"
    "syscall"
    "unsafe"
    "w32"
    "w32/user32"
    "w32/comctl32"
)

func internalTrackMouseEvent(hwnd w32.HWND) {
    var tme w32.TRACKMOUSEEVENT
    tme.CbSize = uint(unsafe.Sizeof(tme))
    tme.DwFlags = w32.TME_LEAVE
    tme.HwndTrack = hwnd
    tme.DwHoverTime = w32.HOVER_DEFAULT

    comctl32.TrackMouseEvent(&tme)
}

func ToggleStyle(hwnd w32.HWND, b bool, style int) {
    originalStyle := int(user32.GetWindowLongPtr(hwnd, w32.GWL_STYLE))
    if originalStyle != 0 {
        if b {
            originalStyle |= style
        } else {
            originalStyle ^= style
        }
        user32.SetWindowLongPtr(hwnd, w32.GWL_STYLE, uintptr(originalStyle))
    }
}

func ToggleExStyle(hwnd w32.HWND, b bool, style int) {
    originalStyle := int(user32.GetWindowLongPtr(hwnd, w32.GWL_EXSTYLE))
    if originalStyle != 0 {
        if b {
            originalStyle |= style
        } else {
            originalStyle ^= style
        }
        user32.SetWindowLongPtr(hwnd, w32.GWL_EXSTYLE, uintptr(originalStyle))
    }
}

func CreateWindow(className string, parent Controller, exStyle, style uint) w32.HWND {
    instance := GetAppInstance()
    var parentHwnd w32.HWND
    if parent != nil {
        parentHwnd = parent.Handle()
    }
    var hwnd w32.HWND
    hwnd = user32.CreateWindowEx(
        exStyle,
        syscall.StringToUTF16Ptr(className),
        nil,
        style,
        w32.CW_USEDEFAULT,
        w32.CW_USEDEFAULT,
        w32.CW_USEDEFAULT,
        w32.CW_USEDEFAULT,
        parentHwnd,
        0,
        instance,
        nil)

    if hwnd == 0 {
        errStr := fmt.Sprintf("Error occurred in CreateWindow(%s, %v, %d, %d)", className, parent, exStyle, style)
        panic(errStr)
    }

    return hwnd
}

func RegisterClass(className string, wndproc uintptr) {
    instance := GetAppInstance()
    icon := user32.LoadIcon(instance, w32.MakeIntResource(w32.IDI_APPLICATION))

    var wc w32.WNDCLASSEX
    wc.Size = uint(unsafe.Sizeof(wc))
    wc.Style = w32.CS_HREDRAW | w32.CS_VREDRAW
    wc.WndProc = wndproc
    wc.Instance = instance
    wc.Background = w32.COLOR_BTNFACE + 1
    wc.Icon = icon
    wc.Cursor = user32.LoadCursor(0, w32.MakeIntResource(w32.IDC_ARROW))
    wc.ClassName = syscall.StringToUTF16Ptr(className)
    wc.MenuName = nil
    wc.IconSm = icon

    if ret := user32.RegisterClassEx(&wc); ret == 0 {
        panic(syscall.GetLastError())
    }
}

func RegClassOnlyOnce(className string) {
    isExists := false
    for _, class := range gRegisteredClasses {
        if class == className {
            isExists = true
            break
        }
    }

    if !isExists {
        RegisterClass(className, GeneralWndprocCallBack)
        gRegisteredClasses = append(gRegisteredClasses, className)
    }
}

func ScreenToClientRect(hwnd w32.HWND, rect *w32.RECT) *Rect {
    l, t, r, b := rect.Left, rect.Top, rect.Right, rect.Bottom

    l, t = user32.ScreenToClient(hwnd, l, t)
    r, b = user32.ScreenToClient(hwnd, r, b)
    return NewRect(l, t, r, b)
}<|endoftext|>