<commit_before>package main

import (
	"fmt"
	"io"
	"launchpad.net/xmlpath"
	"log"
	"net/http"
	"strconv"
	"time"
)

const baseURL = "http://www.yr.no/sted/%s/varsel.xml"

type Yrno struct {
}

// Store weather information by date with history of forecasted temperatures
type DayForecast struct {
	Date      time.Time        // same as key of in memory map
	Forecasts map[int]Forecast // contains day periods 0 - 3 by six hours
}
type Forecast struct {
	History map[time.Time]int // contains forecasted temperature in time
}
type Update struct {
	Updated     time.Time
	Date        time.Time
	Period      int
	Temperature int
}

// Fetches latest weather forecast for given location
func (weather Yrno) Fetch(location string) ([]Update, error) {
	var xmlURL string = fmt.Sprintf(baseURL, location)
	log.Printf("Fetching XML data from %s...\n", xmlURL)

	resp, err := http.Get(xmlURL)
	if err != nil {
		// handle error
		log.Print(err)
		return nil, err
	}
	defer resp.Body.Close()

	// parse current forecast
	updates := parseXml(resp.Body)

	return updates, nil
}

// Merges updated forecast into an existing forecasts
func (weather Yrno) MergeUpdates(existing map[time.Time]DayForecast, updates []Update) map[time.Time]DayForecast {
	var results map[time.Time]DayForecast = make(map[time.Time]DayForecast)

	for _, update := range updates {
		period := update.Period
		updated := update.Updated
		temp := update.Temperature

		// apply updates to in memory struct
		if current, ok := existing[update.Date]; ok {
			// store update forecast
			current.Forecasts[period].History[updated] = temp
			results[update.Date] = current
		} else {
			// inititialize struct
			current := DayForecast{
				update.Date,
				make(map[int]Forecast),
			}
			current.Forecasts[update.Period] = Forecast{
				make(map[time.Time]int),
			}
			// store new forecasts
			current.Forecasts[period].History[updated] = temp
			results[update.Date] = current
		}
	}

	return results
}

// Extract current forecasts from XML
func parseXml(r io.Reader) []Update {
	log.Print("Parsing XML file...")

	root, err := xmlpath.Parse(r)
	if err != nil {
		log.Fatal(err)
	}
	log.Print("XML parsed...")

	// define XPath queries
	updatedPath := xmlpath.MustCompile("/weatherdata/meta/lastupdate")
	timePath := xmlpath.MustCompile("/weatherdata/forecast/tabular/time")
	fromPath := xmlpath.MustCompile("./@from")
	periodPath := xmlpath.MustCompile("./@period")
	tempPath := xmlpath.MustCompile("./temperature/@value")

	// date of forecast update
	var updated time.Time = parseXmlDate(applyXPath(updatedPath, root))

	var results []Update
	iter := timePath.Iter(root)
	for iter.Next() {
		// forecasted day
		update := Update{
			updated,
			parseXmlDate(applyXPath(fromPath, iter.Node())).Local(),
			parseInt(applyXPath(periodPath, iter.Node())),
			parseInt(applyXPath(tempPath, iter.Node())),
		}
		results = append(results, update)
	}

	return results
}

func applyXPath(path *xmlpath.Path, node *xmlpath.Node) string {
	var result string = ""
	if value, ok := path.String(node); ok {
		result = value
	}
	return result
}

func parseXmlDate(input string) time.Time {
	t, err := time.Parse("2006-01-02T15:04:05", input)
	if err != nil {
		log.Print(err)
	}
	return t
}

func parseInt(s string) int {
	n, err := strconv.Atoi(s)
	if err != nil {
		log.Print(err)
	}
	return n
}
<commit_msg>Refactor merge functionality and apply lint suggestions<commit_after>package main

import (
	"fmt"
	"io"
	"launchpad.net/xmlpath"
	"log"
	"net/http"
	"strconv"
	"time"
)

const baseURL = "http://www.yr.no/sted/%s/varsel.xml"

type yrno struct {
}

// Store weather information by date with history of forecasted temperatures
type DayForecast struct {
	Date      time.Time        // same as key of in memory map
	Forecasts map[int]Forecast // contains day periods 0 - 3 by six hours
}
type Forecast struct {
	History map[time.Time]int // contains forecasted temperature in time
}

type Update struct {
	Updated     time.Time
	Date        time.Time
	Period      int
	Temperature int
}

// Fetches latest weather forecast for given location
func (weather yrno) Fetch(location string) ([]Update, error) {
	xmlURL := fmt.Sprintf(baseURL, location)
	log.Printf("Fetching XML data from %s...\n", xmlURL)

	resp, err := http.Get(xmlURL)
	if err != nil {
		log.Print(err)
		return nil, err
	}
	defer resp.Body.Close()

	// parse current forecast
	updates := parseXml(resp.Body)

	return updates, nil
}

// Merges updated forecast into an existing forecasts
func (weather yrno) MergeUpdates(existing map[time.Time]DayForecast, updates []Update) {
	for _, update := range updates {
		period := update.Period
		updated := update.Updated

		// apply updates to in memory struct
		if current, ok := existing[update.Date]; ok {
			// store update forecast with updated temperattures
			current.Forecasts[period].History[updated] = update.Temperature
		} else {
			// add new forecast dta
			current := DayForecast{
				update.Date,
				make(map[int]Forecast),
			}
			current.Forecasts[update.Period] = Forecast{
				make(map[time.Time]int),
			}
			current.Forecasts[period].History[updated] = update.Temperature
			existing[update.Date] = current
		}
	}
}

// Extract current forecasts from XML
func parseXML(r io.Reader) []Update {
	log.Print("Parsing XML file...")

	root, err := xmlpath.Parse(r)
	if err != nil {
		log.Fatal(err)
	}
	log.Print("XML parsed...")

	// define XPath queries
	updatedPath := xmlpath.MustCompile("/weatherdata/meta/lastupdate")
	timePath := xmlpath.MustCompile("/weatherdata/forecast/tabular/time")
	fromPath := xmlpath.MustCompile("./@from")
	periodPath := xmlpath.MustCompile("./@period")
	tempPath := xmlpath.MustCompile("./temperature/@value")

	// date of forecast update
	updated := parseXmlDate(applyXPath(updatedPath, root))

	var results []Update
	iter := timePath.Iter(root)
	for iter.Next() {
		// forecasted day
		update := Update{
			updated,
			parseXmlDate(applyXPath(fromPath, iter.Node())).Local(),
			parseInt(applyXPath(periodPath, iter.Node())),
			parseInt(applyXPath(tempPath, iter.Node())),
		}
		results = append(results, update)
	}

	return results
}

func applyXPath(path *xmlpath.Path, node *xmlpath.Node) string {
	var result string
	if value, ok := path.String(node); ok {
		result = value
	}
	return result
}

func parseXMLDate(input string) time.Time {
	t, err := time.Parse("2006-01-02T15:04:05", input)
	if err != nil {
		log.Print(err)
	}
	return t
}

func parseInt(s string) int {
	n, err := strconv.Atoi(s)
	if err != nil {
		log.Print(err)
	}
	return n
}
<|endoftext|>


<commit_before>package geometry

import (
	"fmt"
	"math"
)

type Line2D struct {
	P1, P2 Point2D
}

func (l *Line2D) Angle() float64 {
	dx, dy := l.P2.X - l.P1.X, l.P2.Y - l.P1.Y
	return math.Atan(dy/dx)
}

func (l *Line2D) Length() float64 {
	dx, dy := l.P2.X - l.P1.X, l.P2.Y - l.P1.Y
	return math.Sqrt(dx*dx + dy*dy)
}

func (l Line2D) String() string {
	return fmt.Sprintf("{%v %v}", l.P1, l.P2)
}
<commit_msg>Added line intersection functions.<commit_after>package geometry

import (
	"fmt"
	"math"
)

type Line2D struct {
	P1, P2 Point2D
}

func (l *Line2D) Angle() float64 {
	dx, dy := l.P2.X-l.P1.X, l.P2.Y-l.P1.Y
	return math.Atan(dy / dx)
}

func (l *Line2D) Length() float64 {
	dx, dy := l.P2.X-l.P1.X, l.P2.Y-l.P1.Y
	return math.Sqrt(dx*dx + dy*dy)
}

func (l Line2D) String() string {
	return fmt.Sprintf("{%v %v}", l.P1, l.P2)
}

// Check if two line segments intersect.
// From Graphics Gems III, Faster Line Segment Intersection.
func LinesIntersect2D(l1, l2 Line2D) bool {
	a := l1.P2.Minus(l1.P1)
	b := l2.P1.Minus(l2.P2)
	denominator := a.Y*b.X - a.X*b.Y
	if denominator == 0.0 {
		return false
	}
	c := l1.P1.Minus(l2.P1)
	A := b.Y*c.X - b.X*c.Y
	if denominator > 0 && (A < 0.0 || A > denominator) {
		return false
	}
	B := a.X*c.Y - a.Y*c.X
	if denominator > 0 && (B > 0.0 || B < denominator) {
		return false
	}
	return true
}

// Returns the intersection point and if said point occures on both lines.
// From Graphics Gems III, Faster Line Segment Intersection.
func LinesIntersection2D(l1, l2 Line2D) (Point2D, bool) {
	a := l1.P2.Minus(l1.P1)
	b := l2.P1.Minus(l2.P2)
	denominator := a.Y*b.X - a.X*b.Y
	if denominator == 0.0 {
		return Point2D{math.Inf(1), math.Inf(1)}, false
	}
	denominator = 1.0 / denominator
	c := l1.P1.Minus(l2.P1)
	A := (b.Y*c.X - b.X*c.Y) * denominator
	intersection := l1.P1.Plus(a.Times(A))
	if A < 0.0 || A > 1.0 {
		return intersection, false
	}
	B := (a.X*c.Y - a.Y*c.X) * denominator
	if B < 0.0 || B > 1.0 {
		return intersection, false
	}
	return intersection, true
}
<|endoftext|>


<commit_before>package schedule

import (
	"time"
)

type Commit struct {
	dateTime time.Time
	message  string
}

type Commits []Commit
<commit_msg>Start implementing RandomCommits function.<commit_after>package schedule

import (
	"time"
)

type Commit struct {
	dateTime time.Time
	message  string
}

// RandomCommits returns a channel of random commits for a given day.
func RandomCommits(day time.Time, rnd int) chan Commit {
	commitChannel := make(chan Commit)
	go func() {
		for i := 0; i < rnd; i++ {
			commitChannel <- Commit{
				dateTime: getRandomTime(), message: getRandomCommitMessage(),
			}
		}
	}()
	return commitChannel
}

func getRandomTime() time.Time {
	return time.Now()
}

func getRandomCommitMessage() string {
	return "not so random string"
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestDiffTags(t *testing.T) {
	cases := []struct {
		Old, New       map[string]interface{}
		Create, Remove map[string]string
	}{
		// Basic add/remove
		{
			Old: map[string]interface{}{
				"foo": "bar",
			},
			New: map[string]interface{}{
				"bar": "baz",
			},
			Create: map[string]string{
				"bar": "baz",
			},
			Remove: map[string]string{
				"foo": "bar",
			},
		},

		// Modify
		{
			Old: map[string]interface{}{
				"foo": "bar",
			},
			New: map[string]interface{}{
				"foo": "baz",
			},
			Create: map[string]string{
				"foo": "baz",
			},
			Remove: map[string]string{
				"foo": "bar",
			},
		},
	}

	for i, tc := range cases {
		c, r := diffTags(tagsFromMap(tc.Old), tagsFromMap(tc.New))
		cm := tagsToMap(c)
		rm := tagsToMap(r)
		if !reflect.DeepEqual(cm, tc.Create) {
			t.Fatalf("%d: bad create: %#v", i, cm)
		}
		if !reflect.DeepEqual(rm, tc.Remove) {
			t.Fatalf("%d: bad remove: %#v", i, rm)
		}
	}
}

func TestIgnoringTags(t *testing.T) {
	var ignoredTags []*ec2.Tag
	ignoredTags = append(ignoredTags, &ec2.Tag{

		Key:   aws.String("aws:cloudformation:logical-id"),
		Value: aws.String("foo"),
	})
	ignoredTags = append(ignoredTags, &ec2.Tag{
		Key:   aws.String("aws:foo:bar"),
		Value: aws.String("baz"),
	})
	for _, tag := range ignoredTags {
		if !tagIgnored(tag) {
			t.Fatalf("Tag %v with value %v not ignored, but should be!", *tag.Key, *tag.Value)
		}
	}
}

func TestTagsMapToHash(t *testing.T) {
	cases := []struct {
		Left, Right map[string]interface{}
		MustBeEqual bool
	}{
		{
			Left:        map[string]interface{}{},
			Right:       map[string]interface{}{},
			MustBeEqual: true,
		},
		{
			Left: map[string]interface{}{
				"foo": "bar",
				"bar": "baz",
			},
			Right: map[string]interface{}{
				"bar": "baz",
				"foo": "bar",
			},
			MustBeEqual: true,
		},
		{
			Left: map[string]interface{}{
				"foo": "bar",
			},
			Right: map[string]interface{}{
				"bar": "baz",
			},
			MustBeEqual: false,
		},
	}

	for i, tc := range cases {
		l := tagsMapToHash(tc.Left)
		r := tagsMapToHash(tc.Right)
		if tc.MustBeEqual && (l != r) {
			t.Fatalf("%d: Hashes don't match", i)
		}
		if !tc.MustBeEqual && (l == r) {
			t.Logf("%d: Hashes match", i)
		}
	}
}

// testAccCheckTags can be used to check the tags on a resource.
func testAccCheckTags(
	ts *[]*ec2.Tag, key string, value string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		m := tagsToMap(*ts)
		v, ok := m[key]
		if value != "" && !ok {
			return fmt.Errorf("Missing tag: %s", key)
		} else if value == "" && ok {
			return fmt.Errorf("Extra tag: %s", key)
		}
		if value == "" {
			return nil
		}

		if v != value {
			return fmt.Errorf("%s: bad value: %s", key, v)
		}

		return nil
	}
}
<commit_msg>Fix TestDiffTags to test for duplicate Tag creation.<commit_after>package aws

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestDiffTags(t *testing.T) {
	cases := []struct {
		Old, New       map[string]interface{}
		Create, Remove map[string]string
	}{
		// Add
		{
			Old: map[string]interface{}{
				"foo": "bar",
			},
			New: map[string]interface{}{
				"foo": "bar",
				"bar": "baz",
			},
			Create: map[string]string{
				"bar": "baz",
			},
			Remove: map[string]string{},
		},

		// Modify
		{
			Old: map[string]interface{}{
				"foo": "bar",
			},
			New: map[string]interface{}{
				"foo": "baz",
			},
			Create: map[string]string{
				"foo": "baz",
			},
			Remove: map[string]string{
				"foo": "bar",
			},
		},
		// Remove
		{
			Old: map[string]interface{}{
				"foo": "bar",
				"bar": "baz",
			},
			New: map[string]interface{}{
				"foo": "bar",
			},
			Create: map[string]string{},
			Remove: map[string]string{
				"bar": "baz",
			},
		},
	}

	for i, tc := range cases {
		c, r := diffTags(tagsFromMap(tc.Old), tagsFromMap(tc.New))
		t.Logf("create: %v remove: %v", c, r)
		cm := tagsToMap(c)
		rm := tagsToMap(r)
		t.Logf("maps: create: %v remove: %v", cm, rm)
		if !reflect.DeepEqual(cm, tc.Create) {
			t.Fatalf("%d: bad create: %#v", i, cm)
		}
		if !reflect.DeepEqual(rm, tc.Remove) {
			t.Fatalf("%d: bad remove: %#v", i, rm)
		}
	}
}

func TestIgnoringTags(t *testing.T) {
	var ignoredTags []*ec2.Tag
	ignoredTags = append(ignoredTags, &ec2.Tag{

		Key:   aws.String("aws:cloudformation:logical-id"),
		Value: aws.String("foo"),
	})
	ignoredTags = append(ignoredTags, &ec2.Tag{
		Key:   aws.String("aws:foo:bar"),
		Value: aws.String("baz"),
	})
	for _, tag := range ignoredTags {
		if !tagIgnored(tag) {
			t.Fatalf("Tag %v with value %v not ignored, but should be!", *tag.Key, *tag.Value)
		}
	}
}

func TestTagsMapToHash(t *testing.T) {
	cases := []struct {
		Left, Right map[string]interface{}
		MustBeEqual bool
	}{
		{
			Left:        map[string]interface{}{},
			Right:       map[string]interface{}{},
			MustBeEqual: true,
		},
		{
			Left: map[string]interface{}{
				"foo": "bar",
				"bar": "baz",
			},
			Right: map[string]interface{}{
				"bar": "baz",
				"foo": "bar",
			},
			MustBeEqual: true,
		},
		{
			Left: map[string]interface{}{
				"foo": "bar",
			},
			Right: map[string]interface{}{
				"bar": "baz",
			},
			MustBeEqual: false,
		},
	}

	for i, tc := range cases {
		l := tagsMapToHash(tc.Left)
		r := tagsMapToHash(tc.Right)
		if tc.MustBeEqual && (l != r) {
			t.Fatalf("%d: Hashes don't match", i)
		}
		if !tc.MustBeEqual && (l == r) {
			t.Logf("%d: Hashes match", i)
		}
	}
}

// testAccCheckTags can be used to check the tags on a resource.
func testAccCheckTags(
	ts *[]*ec2.Tag, key string, value string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		m := tagsToMap(*ts)
		v, ok := m[key]
		if value != "" && !ok {
			return fmt.Errorf("Missing tag: %s", key)
		} else if value == "" && ok {
			return fmt.Errorf("Extra tag: %s", key)
		}
		if value == "" {
			return nil
		}

		if v != value {
			return fmt.Errorf("%s: bad value: %s", key, v)
		}

		return nil
	}
}
<|endoftext|>


<commit_before>package awscred

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"
)

var oldCredPath string
var tempPath string

func setup(t *testing.T) {
	oldCredPath = credPath
	path, err := ioutil.TempDir("", "")
	if err != nil {
		credPath = oldCredPath
		t.Fatal(err)
	}
	credPath = fmt.Sprint(path, "/credentials")
}

func teardown(t *testing.T) {
	credPath = oldCredPath
	err := os.RemoveAll(tempPath)
	if err != nil {
		t.Fatal(err)
	}
}

func checkContent(t *testing.T, expected string) {
	c, err := ioutil.ReadFile(credPath)
	if err != nil {
		t.Fatal(err)
	}
	got := string(c)
	if expected != got {
		t.Errorf("\nexpected:\n---\n%s---\ngot:\n---\n%s---", expected, got)
	}
}

func writeCreds(t *testing.T, c string) {
	err := ioutil.WriteFile(credPath, []byte(c), 0777)
	if err != nil {
		t.Fatal(err)
	}
}

func TestNoConfig(t *testing.T) {
	setup(t)
	defer teardown(t)

	expected := `[adfs]
aws_access_key_id     = key
aws_secret_access_key = secret
aws_session_token     = token

`
	c := Credentials{"key", "secret", "token"}
	c.Write()
	checkContent(t, expected)
}

func TestDefaultCredsExist(t *testing.T) {
	setup(t)
	defer teardown(t)

	existingCreds := `[default]
aws_access_key_id = default_key
aws_secret_access_key = default_secret
`
	writeCreds(t, existingCreds)
	expected := `[default]
aws_access_key_id     = default_key
aws_secret_access_key = default_secret

[adfs]
aws_access_key_id     = key
aws_secret_access_key = secret
aws_session_token     = token

`
	c := Credentials{"key", "secret", "token"}
	c.Write()
	checkContent(t, expected)
}
<commit_msg>add adfs creds exist test case to awscred<commit_after>package awscred

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"
)

var oldCredPath string
var tempPath string

func setup(t *testing.T) {
	oldCredPath = credPath
	path, err := ioutil.TempDir("", "")
	if err != nil {
		credPath = oldCredPath
		t.Fatal(err)
	}
	credPath = fmt.Sprint(path, "/credentials")
}

func teardown(t *testing.T) {
	credPath = oldCredPath
	err := os.RemoveAll(tempPath)
	if err != nil {
		t.Fatal(err)
	}
}

func checkContent(t *testing.T, expected string) {
	c, err := ioutil.ReadFile(credPath)
	if err != nil {
		t.Fatal(err)
	}
	got := string(c)
	if expected != got {
		t.Errorf("\nexpected:\n---\n%s---\ngot:\n---\n%s---", expected, got)
	}
}

func writeCreds(t *testing.T, c string) {
	err := ioutil.WriteFile(credPath, []byte(c), 0777)
	if err != nil {
		t.Fatal(err)
	}
}

func TestNoConfig(t *testing.T) {
	setup(t)
	defer teardown(t)

	expected := `[adfs]
aws_access_key_id     = key
aws_secret_access_key = secret
aws_session_token     = token

`
	c := Credentials{"key", "secret", "token"}
	c.Write()
	checkContent(t, expected)
}

func TestDefaultCredsExist(t *testing.T) {
	setup(t)
	defer teardown(t)

	existingCreds := `[default]
aws_access_key_id = default_key
aws_secret_access_key = default_secret
`
	writeCreds(t, existingCreds)
	expected := `[default]
aws_access_key_id     = default_key
aws_secret_access_key = default_secret

[adfs]
aws_access_key_id     = key
aws_secret_access_key = secret
aws_session_token     = token

`
	c := Credentials{"key", "secret", "token"}
	c.Write()
	checkContent(t, expected)
}

func TestAdfsCredsExist(t *testing.T) {
	setup(t)
	defer teardown(t)

	existingCreds := `[default]
aws_access_key_id = default_key
aws_secret_access_key = default_secret

[adfs]
aws_access_key_id     = old_key
aws_secret_access_key = old_secret
aws_session_token     = old_token
`
	writeCreds(t, existingCreds)
	expected := `[default]
aws_access_key_id     = default_key
aws_secret_access_key = default_secret

[adfs]
aws_access_key_id     = key
aws_secret_access_key = secret
aws_session_token     = token

`
	c := Credentials{"key", "secret", "token"}
	c.Write()
	checkContent(t, expected)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io"
	"io/ioutil"
	"launchpad.net/goyaml"
	"path/filepath"
	"strings"

	"github.com/russross/blackfriday"
)

// A Page represents the key-value pairs in a page or posts front-end YAML as
// well as the markup in the body.
type Page map[string]interface{}

// ParsePage will parse a file with front-end YAML and markup content, and
// return a key-value Page structure.
func ParsePage(fn string) (Page, error) {
	c, err := ioutil.ReadFile(fn)
	if err != nil {
		return nil, err
	}
	return parsePage(fn, c)
}

// Helper function that creates a new Page from a byte array, parsing the
// front-end YAML and the markup, and pre-calculating all page-level variables.
func parsePage(fn string, c []byte) (Page, error) {

	page, err := parseMatter(c) //map[string] interface{} { }
	if err != nil {
		return nil, err
	}

	ext := filepath.Ext(fn)
	ext_output := ext
	markdown := isMarkdown(fn)

	// if markdown, change the output extension to html
	if markdown {
		ext_output = ".html"
	}

	page["ext"] = ext
	page["output_ext"] = ext_output
	page["id"] = removeExt(fn)
	page["url"] = replaceExt(fn, ext_output)

	// if markdown, convert to html
	raw := parseContent(c)
	if markdown {
		page["content"] = string(blackfriday.MarkdownCommon(raw))
	} else {
		page["content"] = string(raw)
	}

	if page["layout"] == "" {
		page["layout"] = "default"
	}

	// according to spec, Jekyll allows user to enter either category or
	// categories. Convert single category to string array to be consistent ...
	if category := page.GetString("category"); category != "" {
		page["categories"] = []string{ category }
		delete(page, "category")
	}

	return page, nil
}

// Helper function to parse the front-end yaml matter.
func parseMatter(content []byte) (Page, error) {
	page := map[string] interface{} { }
	err := goyaml.Unmarshal(content, &page)
	return page, err
}

// Helper function that separates the front-end yaml from the markup, and
// and returns only the markup (content) as a byte array.
func parseContent(content []byte) []byte {
	//now we need to parse out the markdown section create
	//buffered reader
	b := bytes.NewBuffer(content)
	m := new(bytes.Buffer)
	streams := 0

	//read each line of the file and read the markdown section
	//which is the second document stream in the yaml file
	parse : for {
		line, err := b.ReadString('\n')
		switch {
		case err == io.EOF && streams >= 2:
			m.WriteString(line)
			break parse
		case err == io.EOF:
			break parse
		case err != nil :
			return nil
		case streams >= 2:
			m.WriteString(line)
		case strings.HasPrefix(line, "---") :
			streams++
		}
	}

	return m.Bytes()
}

// Sets a parameter value.
func (p Page) Set(key string, val interface{}) {
	p[key] = val
}

// Gets a parameter value.
func (p Page) Get(key string) interface{} {
	return p[key]
}

// Gets a parameter value as a string. If none exists return an empty string.
func (p Page) GetString(key string) (str string) {
	if v, ok := p[key]; ok {
		str = v.(string)
	}
	return
}

// Gets a parameter value as a string array.
func (p Page) GetStrings(key string) (strs []string) {
	if v, ok := p[key]; ok {
		for _, s := range v.([]interface{}) {
			strs = append(strs, s.(string))
		}
	}
	return
}

// Gets a parameter value as a byte array.
func (p Page) GetBytes(key string) (b []byte) {
	if v, ok := p[key]; ok {
		b = v.([]byte)
	}
	return
}

// Gets the layout file to use, without the extension.
// Layout files must be placed in the _layouts directory.
func (p Page) GetLayout() string {
	return p.GetString("layout")
}

// Gets the title of the Page.
func (p Page) GetTitle() string {
	return p.GetString("title")
}

// Gets the URL / relative path of the Page.
// e.g. /2008/12/14/my-post.html
func (p Page) GetUrl() string {
	return p.GetString("url")
}

// Gets the Extension of the File (.html, .md, etc)
func (p Page) GetExt() string {
	return p.GetString("ext")
}

// Gets the un-rendered content of the Page.
func (p Page) GetContent() (c string) {
	if v, ok := p["content"]; ok {
		c = v.(string)
	}
	return
}

// Gets the list of tags to which this Post belongs.
func (p Page) GetTags() []string {
	return p.GetStrings("tags")
}

// Gets the list of categories to which this post belongs.
func (p Page) GetCategories() []string {
	return p.GetStrings("categories")
}

<commit_msg>Make default layout actually trigger.<commit_after>package main

import (
	"bytes"
	"io"
	"io/ioutil"
	"launchpad.net/goyaml"
	"path/filepath"
	"strings"

	"github.com/russross/blackfriday"
)

// A Page represents the key-value pairs in a page or posts front-end YAML as
// well as the markup in the body.
type Page map[string]interface{}

// ParsePage will parse a file with front-end YAML and markup content, and
// return a key-value Page structure.
func ParsePage(fn string) (Page, error) {
	c, err := ioutil.ReadFile(fn)
	if err != nil {
		return nil, err
	}
	return parsePage(fn, c)
}

// Helper function that creates a new Page from a byte array, parsing the
// front-end YAML and the markup, and pre-calculating all page-level variables.
func parsePage(fn string, c []byte) (Page, error) {

	page, err := parseMatter(c) //map[string] interface{} { }
	if err != nil {
		return nil, err
	}

	ext := filepath.Ext(fn)
	ext_output := ext
	markdown := isMarkdown(fn)

	// if markdown, change the output extension to html
	if markdown {
		ext_output = ".html"
	}

	page["ext"] = ext
	page["output_ext"] = ext_output
	page["id"] = removeExt(fn)
	page["url"] = replaceExt(fn, ext_output)

	// if markdown, convert to html
	raw := parseContent(c)
	if markdown {
		page["content"] = string(blackfriday.MarkdownCommon(raw))
	} else {
		page["content"] = string(raw)
	}

	if page["layout"] == nil {
		page["layout"] = "default"
	}

	// according to spec, Jekyll allows user to enter either category or
	// categories. Convert single category to string array to be consistent ...
	if category := page.GetString("category"); category != "" {
		page["categories"] = []string{ category }
		delete(page, "category")
	}

	return page, nil
}

// Helper function to parse the front-end yaml matter.
func parseMatter(content []byte) (Page, error) {
	page := map[string] interface{} { }
	err := goyaml.Unmarshal(content, &page)
	return page, err
}

// Helper function that separates the front-end yaml from the markup, and
// and returns only the markup (content) as a byte array.
func parseContent(content []byte) []byte {
	//now we need to parse out the markdown section create
	//buffered reader
	b := bytes.NewBuffer(content)
	m := new(bytes.Buffer)
	streams := 0

	//read each line of the file and read the markdown section
	//which is the second document stream in the yaml file
	parse : for {
		line, err := b.ReadString('\n')
		switch {
		case err == io.EOF && streams >= 2:
			m.WriteString(line)
			break parse
		case err == io.EOF:
			break parse
		case err != nil :
			return nil
		case streams >= 2:
			m.WriteString(line)
		case strings.HasPrefix(line, "---") :
			streams++
		}
	}

	return m.Bytes()
}

// Sets a parameter value.
func (p Page) Set(key string, val interface{}) {
	p[key] = val
}

// Gets a parameter value.
func (p Page) Get(key string) interface{} {
	return p[key]
}

// Gets a parameter value as a string. If none exists return an empty string.
func (p Page) GetString(key string) (str string) {
	if v, ok := p[key]; ok {
		str = v.(string)
	}
	return
}

// Gets a parameter value as a string array.
func (p Page) GetStrings(key string) (strs []string) {
	if v, ok := p[key]; ok {
		for _, s := range v.([]interface{}) {
			strs = append(strs, s.(string))
		}
	}
	return
}

// Gets a parameter value as a byte array.
func (p Page) GetBytes(key string) (b []byte) {
	if v, ok := p[key]; ok {
		b = v.([]byte)
	}
	return
}

// Gets the layout file to use, without the extension.
// Layout files must be placed in the _layouts directory.
func (p Page) GetLayout() string {
	return p.GetString("layout")
}

// Gets the title of the Page.
func (p Page) GetTitle() string {
	return p.GetString("title")
}

// Gets the URL / relative path of the Page.
// e.g. /2008/12/14/my-post.html
func (p Page) GetUrl() string {
	return p.GetString("url")
}

// Gets the Extension of the File (.html, .md, etc)
func (p Page) GetExt() string {
	return p.GetString("ext")
}

// Gets the un-rendered content of the Page.
func (p Page) GetContent() (c string) {
	if v, ok := p["content"]; ok {
		c = v.(string)
	}
	return
}

// Gets the list of tags to which this Post belongs.
func (p Page) GetTags() []string {
	return p.GetStrings("tags")
}

// Gets the list of categories to which this post belongs.
func (p Page) GetCategories() []string {
	return p.GetStrings("categories")
}

<|endoftext|>


<commit_before>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package set

import (
	"sort"
)

// Strings represents the classic "set" data structure, and contains
// strings.
type Strings struct {
	values map[string]bool
}

// NewStrings creates and initializes a Strings and populates it with
// initial values as specified in the parameters.
func NewStrings(initial ...string) Strings {
	result := Strings{values: make(map[string]bool)}
	for _, value := range initial {
		result.Add(value)
	}
	return result
}

// Size returns the number of elements in the set.
func (s *Strings) Size() int {
	return len(s.values)
}

// IsEmpty is true for empty or uninitialized sets.
func (s *Strings) IsEmpty() bool {
	return len(s.values) == 0
}

// Add puts a value into the set.
func (s *Strings) Add(value string) {
	if s.values == nil {
		s.values = make(map[string]bool)
	}
	s.values[value] = true
}

// Remove takes a value out of the set.  If value wasn't in the set to start
// with, this method silently succeeds.
func (s *Strings) Remove(value string) {
	if s.values == nil {
		return
	}
	delete(s.values, value)
}

// Contains returns true if the value is in the set, and false otherwise.
func (s *Strings) Contains(value string) bool {
	if s.values == nil {
		return false
	}
	_, exists := s.values[value]
	return exists
}

// Values returns an unordered slice containing all the values in the set.
func (s *Strings) Values() []string {
	result := make([]string, len(s.values))
	i := 0
	for key := range s.values {
		result[i] = key
		i++
	}
	return result
}

// SortedValues returns an ordered slice containing all the values in the set.
func (s *Strings) SortedValues() []string {
	values := s.Values()
	sort.Strings(values)
	return values
}

// Union returns a new Strings representing a union of the elments in the
// method target and the parameter.
func (s *Strings) Union(other Strings) Strings {
	result := NewStrings()
	// Use the internal map rather than going through the friendlier functions
	// to avoid extra allocation of slices.
	for value := range s.values {
		result.values[value] = true
	}
	for value := range other.values {
		result.values[value] = true
	}
	return result
}

// Intersection returns a new Strings representing a intersection of the elments in the
// method target and the parameter.
func (s *Strings) Intersection(other Strings) Strings {
	result := NewStrings()
	// Use the internal map rather than going through the friendlier functions
	// to avoid extra allocation of slices.
	for value := range s.values {
		if other.Contains(value) {
			result.values[value] = true
		}
	}
	return result
}

// Difference returns a new Strings representing all the values in the
// target that are not in the parameter.
func (s *Strings) Difference(other Strings) Strings {
	result := NewStrings()
	// Use the internal map rather than going through the friendlier functions
	// to avoid extra allocation of slices.
	for value := range s.values {
		if !other.Contains(value) {
			result.values[value] = true
		}
	}
	return result
}
<commit_msg>utils/set: use value methods consistently<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package set

import (
	"sort"
)

// Strings represents the classic "set" data structure, and contains
// strings.
type Strings struct {
	values map[string]bool
}

// NewStrings creates and initializes a Strings and populates it with
// initial values as specified in the parameters.
func NewStrings(initial ...string) Strings {
	result := Strings{values: make(map[string]bool)}
	for _, value := range initial {
		result.Add(value)
	}
	return result
}

// Size returns the number of elements in the set.
func (s Strings) Size() int {
	return len(s.values)
}

// IsEmpty is true for empty or uninitialized sets.
func (s Strings) IsEmpty() bool {
	return len(s.values) == 0
}

// Add puts a value into the set.
func (s *Strings) Add(value string) {
	if s.values == nil {
		s.values = make(map[string]bool)
	}
	s.values[value] = true
}

// Remove takes a value out of the set.  If value wasn't in the set to start
// with, this method silently succeeds.
func (s Strings) Remove(value string) {
	delete(s.values, value)
}

// Contains returns true if the value is in the set, and false otherwise.
func (s Strings) Contains(value string) bool {
	_, exists := s.values[value]
	return exists
}

// Values returns an unordered slice containing all the values in the set.
func (s Strings) Values() []string {
	result := make([]string, len(s.values))
	i := 0
	for key := range s.values {
		result[i] = key
		i++
	}
	return result
}

// SortedValues returns an ordered slice containing all the values in the set.
func (s Strings) SortedValues() []string {
	values := s.Values()
	sort.Strings(values)
	return values
}

// Union returns a new Strings representing a union of the elments in the
// method target and the parameter.
func (s Strings) Union(other Strings) Strings {
	result := NewStrings()
	// Use the internal map rather than going through the friendlier functions
	// to avoid extra allocation of slices.
	for value := range s.values {
		result.values[value] = true
	}
	for value := range other.values {
		result.values[value] = true
	}
	return result
}

// Intersection returns a new Strings representing a intersection of the elments in the
// method target and the parameter.
func (s Strings) Intersection(other Strings) Strings {
	result := NewStrings()
	// Use the internal map rather than going through the friendlier functions
	// to avoid extra allocation of slices.
	for value := range s.values {
		if other.Contains(value) {
			result.values[value] = true
		}
	}
	return result
}

// Difference returns a new Strings representing all the values in the
// target that are not in the parameter.
func (s Strings) Difference(other Strings) Strings {
	result := NewStrings()
	// Use the internal map rather than going through the friendlier functions
	// to avoid extra allocation of slices.
	for value := range s.values {
		if !other.Contains(value) {
			result.values[value] = true
		}
	}
	return result
}
<|endoftext|>


<commit_before>package geometry

import "math"

// A Line3D representes a 3D line by two points P1 and P2 (represented by
// vectors) on the line. The line is treated as an infinite line unless a
// method explicitly says otherwise. If treated as a segment then P1 and P2 are
// the end points of the line segment.
type Line3D struct {
	P1, P2 Vector3D
}

// Equal compares a and b and returns a boolean indicating if they are equal.
func (a *Line3D) Equal(b *Line3D) bool {
	l1dx, l1dy, l1dz := a.P2.X-a.P1.X, a.P2.Y-a.P1.Y, a.P2.Z-a.P1.Z
	d := 1 / (l1dx*l1dx + l1dy*l1dy + l1dz*l1dz)
	u := (l1dx*(b.P1.X-a.P1.X) + l1dy*(b.P1.Y-a.P1.Y) + l1dz*(b.P1.Z-a.P1.Z)) * d
	x, y, z := b.P1.X-(a.P1.X+l1dx*u), b.P1.Y-(a.P1.Y+l1dy*u), b.P1.Z-(a.P1.Z+l1dz*u)
	if x*x+y*y+z*z != 0 {
		return false
	}
	il1dx, il2dx := 1/l1dx, 1/(b.P2.X-b.P1.X)
	return l1dy*il1dx == (b.P2.Y-b.P1.Y)*il2dx && l1dz*il1dx == (b.P2.Z-b.P1.Z)*il2dx
}

// FuzzyEqual compares a and b and returns a boolean indicating if they are
// very close.
func (a *Line3D) FuzzyEqual(b *Line3D) bool {
	l1dx, l1dy, l1dz := a.P2.X-a.P1.X, a.P2.Y-a.P1.Y, a.P2.Z-a.P1.Z
	d := 1 / (l1dx*l1dx + l1dy*l1dy + l1dz*l1dz)
	u := (l1dx*(b.P1.X-a.P1.X) + l1dy*(b.P1.Y-a.P1.Y) + l1dz*(b.P1.Z-a.P1.Z)) * d
	x, y, z := b.P1.X-(a.P1.X+l1dx*u), b.P1.Y-(a.P1.Y+l1dy*u), b.P1.Z-(a.P1.Z+l1dz*u)
	if x*x+y*y+z*z >= 0.000000000001*0.000000000001 {
		return false
	}
	il1dx, il2dx := 1/l1dx, 1/(b.P2.X-b.P1.X)
	dyr := l1dy*il1dx - (b.P2.Y-b.P1.Y)*il2dx
	dzr := l1dz*il1dx - (b.P2.Z-b.P1.Z)*il2dx
	return dyr*dyr < 0.000000000001*0.000000000001 && dzr*dzr < 0.000000000001*0.000000000001
}

// LineBetween sets z to the shortest line between a and b and returns z. This
// function is intended as a replacement for intersection (which can be still
// be tested by z.P1 == z.P2).
func (z *Line3D) LineBetween(a, b *Line3D) *Line3D {
	// http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline3d/
	adx, ady, adz := a.P2.X-a.P1.X, a.P2.Y-a.P1.Y, a.P2.Z-a.P1.Z
	bdx, bdy, bdz := b.P2.X-b.P1.X, b.P2.Y-b.P1.Y, b.P2.Z-b.P1.Z
	p1dx, p1dy, p1dz := a.P1.X-b.P1.X, a.P1.Y-b.P1.Y, a.P1.Z-b.P1.Z
	d1343 := p1dx*bdx + p1dy*bdy + p1dz*bdz
	d4321 := bdx*adx + bdy*ady + bdz*adz
	d1321 := p1dx*adx + p1dy*ady + p1dz*adz
	d4343 := bdx*bdx + bdy*bdy + bdz*bdz
	d2121 := adx*adx + ady*ady + adz*bdz
	mua := (d1343*d4321 - d1321*d4343) / (d2121*d4343 - d4321*d4321)
	mub := (d1343 + mua*d4321) / d4343
	z.P1.X = adx*mua + a.P1.X
	z.P1.Y = ady*mua + a.P1.Y
	z.P1.Z = adz*mua + a.P1.Z
	z.P2.X = bdx*mub + b.P1.X
	z.P2.Y = bdy*mub + b.P1.Y
	z.P2.Z = bdz*mub + b.P1.Z
	return z
}

// PointDistance returns the distance point b is from line a.
func (a *Line3D) PointDistance(b *Vector3D) float64 {
	// http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
	ldx, ldy, ldz := a.P2.X-a.P1.X, a.P2.Y-a.P1.Y, a.P2.Z-a.P1.Z
	u := (ldx*(b.X-a.P1.X) + ldy*(b.Y-a.P1.Y) + ldz*(b.Z-a.P1.Z)) /
		(ldx*ldx + ldy*ldy + ldz*ldz)
	x, y, z := b.X-(a.P1.X+ldx*u), b.Y-(a.P1.Y+ldy*u), b.Z-(a.P1.Z+ldz*u)
	return math.Sqrt(x*x + y*y + z*z)
}

// PointDistanceSquared returns the squared distance point b is from line a.
func (a *Line3D) PointSquaredDistance(b *Vector3D) float64 {
	// http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
	ldx, ldy, ldz := a.P2.X-a.P1.X, a.P2.Y-a.P1.Y, a.P2.Z-a.P1.Z
	u := (ldx*(b.X-a.P1.X) + ldy*(b.Y-a.P1.Y) + ldz*(b.Z-a.P1.Z)) /
		(ldx*ldx + ldy*ldy + ldz*ldz)
	x, y, z := b.X-(a.P1.X+ldx*u), b.Y-(a.P1.Y+ldy*u), b.Z-(a.P1.Z+ldz*u)
	return x*x + y*y + z*z
}

// SegmentEqual compares a and b as line segments and returns a boolean
// indicating if they are equal.
func (a *Line3D) SegmentEqual(b *Line3D) bool {
	return (a.P1 == b.P1 && a.P2 == b.P2) || (a.P1 == b.P2 && a.P2 == b.P1)
}

// SegmentFuzzyEqual compares a and b as line segments and returns a boolean
// indicating if they are very close.
func (a *Line3D) SegmentFuzzyEqual(b *Line3D) bool {
	dx1, dy1, dz1 := a.P1.X-b.P1.X, a.P1.Y-b.P1.Y, a.P1.Z-b.P1.Z
	dx2, dy2, dz2 := a.P2.X-b.P2.X, a.P2.Y-b.P2.Y, a.P2.Z-b.P2.Z
	if dx1*dx1+dy1*dy1+dz1*dz1 < 0.000000000001*0.000000000001 &&
		dx2*dx2+dy2*dy2+dz2*dz2 < 0.000000000001*0.000000000001 {
		return true
	}
	dx1, dy1, dz1 = a.P1.X-b.P2.X, a.P1.Y-b.P2.Y, a.P1.Z-b.P2.Z
	dx2, dy2, dz2 = a.P2.X-b.P1.X, a.P2.Y-b.P1.Y, a.P2.Z-b.P1.Z
	return dx1*dx1+dy1*dy1+dz1*dz1 < 0.000000000001*0.000000000001 &&
		dx2*dx2+dy2*dy2+dz2*dz2 < 0.000000000001*0.000000000001
}
<commit_msg>Cosmetic changes.<commit_after>package geometry

import "math"

// A Line3D representes a 3D line by two points P1 and P2 (represented by
// vectors) on the line. The line is treated as an infinite line unless a
// method explicitly says otherwise. If treated as a segment then P1 and P2 are
// the end points of the line segment.
type Line3D struct {
	P1, P2 Vector3D
}

// Equal compares a and b and returns a boolean indicating if they are equal.
func (a *Line3D) Equal(b *Line3D) bool {
	l1dx, l1dy, l1dz := a.P2.X-a.P1.X, a.P2.Y-a.P1.Y, a.P2.Z-a.P1.Z
	d := 1 / (l1dx*l1dx + l1dy*l1dy + l1dz*l1dz)
	u := (l1dx*(b.P1.X-a.P1.X) + l1dy*(b.P1.Y-a.P1.Y) + l1dz*(b.P1.Z-a.P1.Z)) * d
	x, y, z := b.P1.X-(a.P1.X+l1dx*u), b.P1.Y-(a.P1.Y+l1dy*u), b.P1.Z-(a.P1.Z+l1dz*u)
	if x*x+y*y+z*z != 0 {
		return false
	}
	il1dx, il2dx := 1/l1dx, 1/(b.P2.X-b.P1.X)
	return l1dy*il1dx == (b.P2.Y-b.P1.Y)*il2dx &&
		l1dz*il1dx == (b.P2.Z-b.P1.Z)*il2dx
}

// FuzzyEqual compares a and b and returns a boolean indicating if they are
// very close.
func (a *Line3D) FuzzyEqual(b *Line3D) bool {
	l1dx, l1dy, l1dz := a.P2.X-a.P1.X, a.P2.Y-a.P1.Y, a.P2.Z-a.P1.Z
	d := 1 / (l1dx*l1dx + l1dy*l1dy + l1dz*l1dz)
	u := (l1dx*(b.P1.X-a.P1.X) + l1dy*(b.P1.Y-a.P1.Y) + l1dz*(b.P1.Z-a.P1.Z)) * d
	x, y, z := b.P1.X-(a.P1.X+l1dx*u), b.P1.Y-(a.P1.Y+l1dy*u), b.P1.Z-(a.P1.Z+l1dz*u)
	if x*x+y*y+z*z >= 0.000000000001*0.000000000001 {
		return false
	}
	il1dx, il2dx := 1/l1dx, 1/(b.P2.X-b.P1.X)
	dyr := l1dy*il1dx - (b.P2.Y-b.P1.Y)*il2dx
	dzr := l1dz*il1dx - (b.P2.Z-b.P1.Z)*il2dx
	return dyr*dyr < 0.000000000001*0.000000000001 &&
		dzr*dzr < 0.000000000001*0.000000000001
}

// LineBetween sets z to the shortest line between a and b and returns z. This
// function is intended as a replacement for intersection (which can be still
// be tested by z.P1 == z.P2).
func (z *Line3D) LineBetween(a, b *Line3D) *Line3D {
	// http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline3d/
	adx, ady, adz := a.P2.X-a.P1.X, a.P2.Y-a.P1.Y, a.P2.Z-a.P1.Z
	bdx, bdy, bdz := b.P2.X-b.P1.X, b.P2.Y-b.P1.Y, b.P2.Z-b.P1.Z
	p1dx, p1dy, p1dz := a.P1.X-b.P1.X, a.P1.Y-b.P1.Y, a.P1.Z-b.P1.Z
	d1343 := p1dx*bdx + p1dy*bdy + p1dz*bdz
	d4321 := bdx*adx + bdy*ady + bdz*adz
	d1321 := p1dx*adx + p1dy*ady + p1dz*adz
	d4343 := bdx*bdx + bdy*bdy + bdz*bdz
	d2121 := adx*adx + ady*ady + adz*bdz
	mua := (d1343*d4321 - d1321*d4343) / (d2121*d4343 - d4321*d4321)
	mub := (d1343 + mua*d4321) / d4343
	z.P1.X = adx*mua + a.P1.X
	z.P1.Y = ady*mua + a.P1.Y
	z.P1.Z = adz*mua + a.P1.Z
	z.P2.X = bdx*mub + b.P1.X
	z.P2.Y = bdy*mub + b.P1.Y
	z.P2.Z = bdz*mub + b.P1.Z
	return z
}

// PointDistance returns the distance point b is from line a.
func (a *Line3D) PointDistance(b *Vector3D) float64 {
	// http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
	ldx, ldy, ldz := a.P2.X-a.P1.X, a.P2.Y-a.P1.Y, a.P2.Z-a.P1.Z
	u := (ldx*(b.X-a.P1.X) + ldy*(b.Y-a.P1.Y) + ldz*(b.Z-a.P1.Z)) /
		(ldx*ldx + ldy*ldy + ldz*ldz)
	x, y, z := b.X-(a.P1.X+ldx*u), b.Y-(a.P1.Y+ldy*u), b.Z-(a.P1.Z+ldz*u)
	return math.Sqrt(x*x + y*y + z*z)
}

// PointDistanceSquared returns the squared distance point b is from line a.
func (a *Line3D) PointSquaredDistance(b *Vector3D) float64 {
	// http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
	ldx, ldy, ldz := a.P2.X-a.P1.X, a.P2.Y-a.P1.Y, a.P2.Z-a.P1.Z
	u := (ldx*(b.X-a.P1.X) + ldy*(b.Y-a.P1.Y) + ldz*(b.Z-a.P1.Z)) /
		(ldx*ldx + ldy*ldy + ldz*ldz)
	x, y, z := b.X-(a.P1.X+ldx*u), b.Y-(a.P1.Y+ldy*u), b.Z-(a.P1.Z+ldz*u)
	return x*x + y*y + z*z
}

// SegmentEqual compares a and b as line segments and returns a boolean
// indicating if they are equal.
func (a *Line3D) SegmentEqual(b *Line3D) bool {
	return (a.P1 == b.P1 && a.P2 == b.P2) || (a.P1 == b.P2 && a.P2 == b.P1)
}

// SegmentFuzzyEqual compares a and b as line segments and returns a boolean
// indicating if they are very close.
func (a *Line3D) SegmentFuzzyEqual(b *Line3D) bool {
	dx1, dy1, dz1 := a.P1.X-b.P1.X, a.P1.Y-b.P1.Y, a.P1.Z-b.P1.Z
	dx2, dy2, dz2 := a.P2.X-b.P2.X, a.P2.Y-b.P2.Y, a.P2.Z-b.P2.Z
	if dx1*dx1+dy1*dy1+dz1*dz1 < 0.000000000001*0.000000000001 &&
		dx2*dx2+dy2*dy2+dz2*dz2 < 0.000000000001*0.000000000001 {
		return true
	}
	dx1, dy1, dz1 = a.P1.X-b.P2.X, a.P1.Y-b.P2.Y, a.P1.Z-b.P2.Z
	dx2, dy2, dz2 = a.P2.X-b.P1.X, a.P2.Y-b.P1.Y, a.P2.Z-b.P1.Z
	return dx1*dx1+dy1*dy1+dz1*dz1 < 0.000000000001*0.000000000001 &&
		dx2*dx2+dy2*dy2+dz2*dz2 < 0.000000000001*0.000000000001
}
<|endoftext|>


<commit_before>package sdl

import (
	"testing"
)

func TestEventsPushEvent(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	// Remove existing events in the queue
	if _, err := PeepEvents(make([]Event, 100), GETEVENT, FIRSTEVENT, LASTEVENT); err != nil {
		t.Error("PeepEvents:", err)
	}

	PushEvent(&in)

	out, ok := PollEvent().(*UserEvent)
	if !ok {
		t.Errorf("Failed to cast event to *UserEvent")
	}
	if out.Code != in.Code {
		t.Errorf("Expected event code %d but got %d", in.Code, out.Code)
	}
}

type simpleTestFilter struct{}

func (s *simpleTestFilter) FilterEvent(e Event, userdata interface{}) bool {
	return true
}

func TestEventsSetGetEventFilter(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	filter := &simpleTestFilter{}
	SetEventFilter(filter, nil)

	if filter != GetEventFilter() {
		t.Errorf("Could not round-trip the event filter.")
	}

	if !isCEventFilterSet() {
		t.Errorf("Event filter was not actually set in C.")
	}

	SetEventFilter(nil, nil)

	if nil != GetEventFilter() {
		t.Errorf("Event filter was not cleared.")
	}

	if isCEventFilterSet() {
		t.Errorf("Event filter was not actually cleared in C.")
	}
}

func countEventsInQ(wait bool) int {
	var e Event
	if wait {
		e = WaitEvent()
	} else {
		e = PollEvent()
	}

	count := 0
	for ; e != nil; e = PollEvent() {
		count++
	}
	return count
}

func TestEventsSetEventFilter(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	filterFunc := func(e Event, log bool) bool {
		if log {
			t.Log("TestSetEventFilter received", e)
		}

		ue, ok := e.(*UserEvent)
		if !ok {
			return false
		}

		return ue.Code == 42
	}
	SetEventFilterFunc(func(e Event, userdata interface{}) bool {
		return filterFunc(e, true)
	}, nil)

	ins := []*UserEvent{
		{Type: USEREVENT, Code: 42},
		{Type: USEREVENT, Code: 41},
	}

	expectedOutCount := 0
	for _, in := range ins {
		PushEvent(in)
		if filterFunc(in, false) {
			expectedOutCount++
		}
	}

	outCount := countEventsInQ(false)

	if outCount != expectedOutCount {
		t.Errorf("Expected %d events to pass but got %d.", expectedOutCount, outCount)
	}
}

func TestEventsGetEventFilterNilOnStartup(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	if GetEventFilter() != nil {
		t.Errorf("Event filter should be nil on startup.")
	}
	SetEventFilterFunc(func(_ Event, userdata interface{}) bool {
		return true
	}, nil)

	Quit()
	Init(INIT_EVERYTHING)

	if GetEventFilter() != nil {
		t.Errorf("Event filter should be nil on startup.")
	}
}

func TestEventsFilterEventsFuncQ(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	ins := []*UserEvent{
		{Type: USEREVENT, Code: 42},
		{Type: USEREVENT, Code: 41},
	}

	filterFunc := func(e Event, log bool) bool {
		if log {
			t.Log("TestEventsFilterEventsFuncQ received", e)
		}

		ue, ok := e.(*UserEvent)
		if !ok {
			return false
		}

		return ue.Code == 42
	}

	expectedOutCount := 0
	for _, in := range ins {
		PushEvent(in)
		if filterFunc(in, false) {
			expectedOutCount++
		}
	}

	FilterEventsFunc(func(e Event, userdata interface{}) bool {
		return filterFunc(e, true)
	}, nil)

	outCount := countEventsInQ(false)

	if outCount != expectedOutCount {
		t.Errorf("Expected %d events to pass but got %d.", expectedOutCount, outCount)
	}
}

func TestEventsAddEventWatch(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	out := Event(nil)
	watch := func(e Event, userdata interface{}) bool {
		t.Log("TestAddEventWatch received", e)
		out = e
		if val, ok := userdata.(int); !ok || val != 0xDEADBEEF {
			t.Errorf("Failed to get userdata")
		}
		return true
	}

	AddEventWatchFunc(watch, 0xDEADBEEF)
	PushEvent(&in)

	if out == nil {
		t.Errorf("Event from event watch was nil but expected it to be non-nil.")
	}

	outue, ok := out.(*UserEvent)
	if !ok {
		t.Errorf("Failed to cast event to *UserEvent")
	}
	if outue.Code != in.Code {
		t.Errorf("Expected event code %d but got %d", in.Code, outue.Code)
	}
}

func TestEventsEventWatchClearOnStartup(t *testing.T) {
	Init(INIT_EVERYTHING)

	AddEventWatchFunc(func(_ Event, userdata interface{}) bool {
		return true
	}, nil)

	Quit()

	if len(eventWatches) != 0 {
		t.Errorf("Expected go event watches to be cleared but it contains %d contexts", len(eventWatches))
	}
}

func TestEventsAddDelEventWatch(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	out := Event(nil)
	watch := func(e Event, userdata interface{}) bool {
		t.Log("TestAddDelEventWatch received", e)
		out = e
		return true
	}

	handle := AddEventWatchFunc(watch, nil)
	DelEventWatch(handle)
	PushEvent(&in)

	if out != nil {
		t.Errorf("Event was received from event watch after it had been removed.")
	}
}
<commit_msg>sdl/events_test.go: fix crash on macOS (#247)<commit_after>package sdl

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

func TestMain(m *testing.M) {
	// TODO: Find a better way to do this

	runtime.UnlockOSThread() // allow tests to be run on different threads
	exitcode := m.Run()
	runtime.LockOSThread() // tests have run, so relock
	os.Exit(exitcode)
}

func TestEventsPushEvent(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	// Remove existing events in the queue
	if _, err := PeepEvents(make([]Event, 100), GETEVENT, FIRSTEVENT, LASTEVENT); err != nil {
		t.Error("PeepEvents:", err)
	}

	PushEvent(&in)

	out, ok := PollEvent().(*UserEvent)
	if !ok {
		t.Errorf("Failed to cast event to *UserEvent")
	}
	if out.Code != in.Code {
		t.Errorf("Expected event code %d but got %d", in.Code, out.Code)
	}
}

type simpleTestFilter struct{}

func (s *simpleTestFilter) FilterEvent(e Event, userdata interface{}) bool {
	return true
}

func TestEventsSetGetEventFilter(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	filter := &simpleTestFilter{}
	SetEventFilter(filter, nil)

	if filter != GetEventFilter() {
		t.Errorf("Could not round-trip the event filter.")
	}

	if !isCEventFilterSet() {
		t.Errorf("Event filter was not actually set in C.")
	}

	SetEventFilter(nil, nil)

	if nil != GetEventFilter() {
		t.Errorf("Event filter was not cleared.")
	}

	if isCEventFilterSet() {
		t.Errorf("Event filter was not actually cleared in C.")
	}
}

func countEventsInQ(wait bool) int {
	var e Event
	if wait {
		e = WaitEvent()
	} else {
		e = PollEvent()
	}

	count := 0
	for ; e != nil; e = PollEvent() {
		count++
	}
	return count
}

func TestEventsSetEventFilter(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	filterFunc := func(e Event, log bool) bool {
		if log {
			t.Log("TestSetEventFilter received", e)
		}

		ue, ok := e.(*UserEvent)
		if !ok {
			return false
		}

		return ue.Code == 42
	}
	SetEventFilterFunc(func(e Event, userdata interface{}) bool {
		return filterFunc(e, true)
	}, nil)

	ins := []*UserEvent{
		{Type: USEREVENT, Code: 42},
		{Type: USEREVENT, Code: 41},
	}

	expectedOutCount := 0
	for _, in := range ins {
		PushEvent(in)
		if filterFunc(in, false) {
			expectedOutCount++
		}
	}

	outCount := countEventsInQ(false)

	if outCount != expectedOutCount {
		t.Errorf("Expected %d events to pass but got %d.", expectedOutCount, outCount)
	}
}

func TestEventsGetEventFilterNilOnStartup(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	if GetEventFilter() != nil {
		t.Errorf("Event filter should be nil on startup.")
	}
	SetEventFilterFunc(func(_ Event, userdata interface{}) bool {
		return true
	}, nil)

	Quit()
	Init(INIT_EVERYTHING)

	if GetEventFilter() != nil {
		t.Errorf("Event filter should be nil on startup.")
	}
}

func TestEventsFilterEventsFuncQ(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	ins := []*UserEvent{
		{Type: USEREVENT, Code: 42},
		{Type: USEREVENT, Code: 41},
	}

	filterFunc := func(e Event, log bool) bool {
		if log {
			t.Log("TestEventsFilterEventsFuncQ received", e)
		}

		ue, ok := e.(*UserEvent)
		if !ok {
			return false
		}

		return ue.Code == 42
	}

	expectedOutCount := 0
	for _, in := range ins {
		PushEvent(in)
		if filterFunc(in, false) {
			expectedOutCount++
		}
	}

	FilterEventsFunc(func(e Event, userdata interface{}) bool {
		return filterFunc(e, true)
	}, nil)

	outCount := countEventsInQ(false)

	if outCount != expectedOutCount {
		t.Errorf("Expected %d events to pass but got %d.", expectedOutCount, outCount)
	}
}

func TestEventsAddEventWatch(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	out := Event(nil)
	watch := func(e Event, userdata interface{}) bool {
		t.Log("TestAddEventWatch received", e)
		out = e
		if val, ok := userdata.(int); !ok || val != 0xDEADBEEF {
			t.Errorf("Failed to get userdata")
		}
		return true
	}

	AddEventWatchFunc(watch, 0xDEADBEEF)
	PushEvent(&in)

	if out == nil {
		t.Errorf("Event from event watch was nil but expected it to be non-nil.")
	}

	outue, ok := out.(*UserEvent)
	if !ok {
		t.Errorf("Failed to cast event to *UserEvent")
	}
	if outue.Code != in.Code {
		t.Errorf("Expected event code %d but got %d", in.Code, outue.Code)
	}
}

func TestEventsEventWatchClearOnStartup(t *testing.T) {
	Init(INIT_EVERYTHING)

	AddEventWatchFunc(func(_ Event, userdata interface{}) bool {
		return true
	}, nil)

	Quit()

	if len(eventWatches) != 0 {
		t.Errorf("Expected go event watches to be cleared but it contains %d contexts", len(eventWatches))
	}
}

func TestEventsAddDelEventWatch(t *testing.T) {
	Init(INIT_EVERYTHING)
	defer Quit()

	in := UserEvent{
		Type: USEREVENT,
		Code: 42,
	}

	out := Event(nil)
	watch := func(e Event, userdata interface{}) bool {
		t.Log("TestAddDelEventWatch received", e)
		out = e
		return true
	}

	handle := AddEventWatchFunc(watch, nil)
	DelEventWatch(handle)
	PushEvent(&in)

	if out != nil {
		t.Errorf("Event was received from event watch after it had been removed.")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"./dns"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
)

func createRequests(rname string) {
	workerPool.Input <- WorkerInput{Name: rname, Type: dns.TypeA}
	workerPool.Input <- WorkerInput{Name: rname, Type: dns.TypeAAAA}
	workerPool.Input <- WorkerInput{Name: rname, Type: dns.TypeMX}
}

func loadWords(fn string) ([]string, error) {
	b, err := ioutil.ReadFile(fn)
	if err != nil {
		return nil, err
	}
	return strings.Split(string(b), "\n"), nil
}

func zoneCmd(dom, fnWords string) {
	words, err := loadWords(fnWords)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}

	go func() {
		createRequests(dom + ".")

		for _, w := range words {
			rname := w + "." + dom + "."
			if len(w) == 0 {
				continue
			}

			createRequests(rname)

			for i := 0; i < 20; i++ {
				createRequests(w + strconv.Itoa(i) + "." + dom + ".")
			}

		}
		workerPool.Shutdown()
	}()

	for out, ok := <-workerPool.Output; ok; out, ok = <-workerPool.Output {
		if out.Error == nil {
			for _, a := range out.Answer {
				fmt.Println(a)
			}
		} else {
			if err, ok := out.Error.(*DNSError); !ok || err.Rcode != dns.RcodeNameError {
				fmt.Println(out.Name, out.Error)
			}
		}
	}
}
<commit_msg>Add TXT record to zone command<commit_after>package main

import (
	"./dns"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
)

func createRequests(rname string) {
	workerPool.Input <- WorkerInput{Name: rname, Type: dns.TypeA}
	workerPool.Input <- WorkerInput{Name: rname, Type: dns.TypeAAAA}
	workerPool.Input <- WorkerInput{Name: rname, Type: dns.TypeMX}
	workerPool.Input <- WorkerInput{Name: rname, Type: dns.TypeTXT}
}

func loadWords(fn string) ([]string, error) {
	b, err := ioutil.ReadFile(fn)
	if err != nil {
		return nil, err
	}
	return strings.Split(string(b), "\n"), nil
}

func zoneCmd(dom, fnWords string) {
	words, err := loadWords(fnWords)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}

	go func() {
		createRequests(dom + ".")

		for _, w := range words {
			rname := w + "." + dom + "."
			if len(w) == 0 {
				continue
			}

			createRequests(rname)

			for i := 0; i < 20; i++ {
				createRequests(w + strconv.Itoa(i) + "." + dom + ".")
			}

		}
		workerPool.Shutdown()
	}()

	for out, ok := <-workerPool.Output; ok; out, ok = <-workerPool.Output {
		if out.Error == nil {
			for _, a := range out.Answer {
				fmt.Println(a)
			}
		} else {
			if err, ok := out.Error.(*DNSError); !ok || err.Rcode != dns.RcodeNameError {
				fmt.Println(out.Name, out.Error)
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"

	"github.com/cafebazaar/kupak/pkg/pak"
	"github.com/codegangsta/cli"
)

func paks(c *cli.Context) error {
	repo, err := pak.RepoFromURL(c.GlobalString("repo"))
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("can't fetch paks list: %v", err.Error()), -1)
	}
	for i := range repo.Paks {
		fmt.Println("- Name:", repo.Paks[i].Name)
		fmt.Println("  Version:", repo.Paks[i].Version)
		fmt.Println("  URL:", repo.Paks[i].URL)
		if len(repo.Paks[i].Tags) > 0 {
			fmt.Println("  Tags:", "["+strings.Join(repo.Paks[i].Tags, ", ")+"]")
		}
		fmt.Println(" ", strings.Trim(repo.Paks[i].Description, "\n"))
	}
	return nil
}

func spec(c *cli.Context) error {
	pakURL := c.Args().First()
	if pakURL == "" {
		return cli.NewExitError("please specify the pak name", -1)
	}
	p, err := pak.FromURL(pakURL)
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("can't fetch the specified pak: %v", err.Error()), -1)
	}
	fmt.Println("Name:", p.Name)
	fmt.Println("Version:", p.Version)
	if len(p.Tags) > 0 {
		fmt.Println("Tags:", "["+strings.Join(p.Tags, ", ")+"]")
	}
	fmt.Println(strings.Trim(p.Description, "\n"))

	fmt.Println("\nProperties:")
	for i := range p.Properties {
		property := p.Properties[i]
		fmt.Println(" - Name:", property.Name)
		fmt.Println("   Description:", strings.Trim(property.Description, "\n"))
		fmt.Println("   Type:", property.Type)
		if property.Default != nil {
			fmt.Println("   Default:", property.Default)
		}

	}
	return nil
}
<commit_msg>Added repos functionality to paks command<commit_after>package main

import (
	"fmt"
	"strings"

	"github.com/cafebazaar/kupak/pkg/pak"
	"github.com/codegangsta/cli"
)

func paks(c *cli.Context) error {
	repoAddresses := make([]string, 0)
	if c.GlobalIsSet("repo") {
		repoAddresses = append(repoAddresses, c.GlobalString("repo"))
	} else {
		reposFileCreateIfNotExist()
		for _, repoEntry := range reposFileEntries() {
			trimmed := strings.TrimSpace(repoEntry)
			if len(trimmed) > 0 {
				repoAddresses = append(repoAddresses, trimmed)
			}
		}
		if len(repoAddresses) == 0 {
			repoAddresses = append(repoAddresses, "github.com/cafebazaar/paks")
		}
	}

	for _, repoAddress := range repoAddresses {
		repo, err := pak.RepoFromURL(repoAddress)
		if err != nil {
			return cli.NewExitError(fmt.Sprintf("can't fetch paks list: %v", err.Error()), -1)
		}
		fmt.Println("- Repository:", repoAddress)
		for i := range repo.Paks {
			fmt.Println("  - Name:", repo.Paks[i].Name)
			fmt.Println("    Version:", repo.Paks[i].Version)
			fmt.Println("    URL:", repo.Paks[i].URL)
			if len(repo.Paks[i].Tags) > 0 {
				fmt.Println("    Tags:", "["+strings.Join(repo.Paks[i].Tags, ", ")+"]")
			}
			fmt.Println("   ", strings.Trim(repo.Paks[i].Description, "\n"))
		}

	}
	return nil
}

func spec(c *cli.Context) error {
	pakURL := c.Args().First()
	if pakURL == "" {
		return cli.NewExitError("please specify the pak name", -1)
	}
	p, err := pak.FromURL(pakURL)
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("can't fetch the specified pak: %v", err.Error()), -1)
	}
	fmt.Println("Name:", p.Name)
	fmt.Println("Version:", p.Version)
	if len(p.Tags) > 0 {
		fmt.Println("Tags:", "["+strings.Join(p.Tags, ", ")+"]")
	}
	fmt.Println(strings.Trim(p.Description, "\n"))

	fmt.Println("\nProperties:")
	for i := range p.Properties {
		property := p.Properties[i]
		fmt.Println(" - Name:", property.Name)
		fmt.Println("   Description:", strings.Trim(property.Description, "\n"))
		fmt.Println("   Type:", property.Type)
		if property.Default != nil {
			fmt.Println("   Default:", property.Default)
		}

	}
	return nil
}
<|endoftext|>


<commit_before>package enmime

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"fmt"
	"io"
	"mime"
	"mime/quotedprintable"
	"net/textproto"
	"strings"
)

// Part represents a node in the MIME multipart tree.  The Content-Type, Disposition and File Name
// are parsed out of the header for easier access.
type Part struct {
	Header      textproto.MIMEHeader // Header for this Part
	Parent      *Part                // Parent of this part (can be nil)
	FirstChild  *Part                // FirstChild is the top most child of this part
	NextSibling *Part                // NextSibling of this part
	ContentType string               // ContentType header without parameters
	Disposition string               // Content-Disposition header without parameters
	FileName    string               // The file-name from disposition or type header
	Charset     string               // The content charset encoding label
	Errors      []Error              // Errors encountered while parsing this part

	boundary      string    // Boundary marker used within this part
	rawReader     io.Reader // The raw Part content, no decoding or charset conversion
	decodedReader io.Reader // The content decoded from quoted-printable or base64
	utf8Reader    io.Reader // The decoded content converted to UTF-8
}

// NewPart creates a new Part object.  It does not update the parents FirstChild attribute.
func NewPart(parent *Part, contentType string) *Part {
	return &Part{Parent: parent, ContentType: contentType}
}

// Read returns the decoded & UTF-8 converted content; implements io.Reader.
func (p *Part) Read(b []byte) (n int, err error) {
	if p.utf8Reader == nil {
		return 0, io.EOF
	}
	return p.utf8Reader.Read(b)
}

// setupContentHeaders uses Content-Type media params and Content-Disposition headers to populate
// the disposition, filename, and charset fields.
func (p *Part) setupContentHeaders(mediaParams map[string]string) {
	// Determine content disposition, filename, character set
	disposition, dparams, err := parseMediaType(p.Header.Get(hnContentDisposition))
	if err == nil {
		// Disposition is optional
		p.Disposition = disposition
		p.FileName = decodeHeader(dparams[hpFilename])
	}
	if p.FileName == "" && mediaParams[hpName] != "" {
		p.FileName = decodeHeader(mediaParams[hpName])
	}
	if p.FileName == "" && mediaParams[hpFile] != "" {
		p.FileName = decodeHeader(mediaParams[hpFile])
	}
	if p.Charset == "" {
		p.Charset = mediaParams[hpCharset]
	}
}

// buildContentReaders sets up the decodedReader and utf8Reader based on the Part headers.  If no
// translation is required at a particular stage, the reader will be the same as its predecessor.
// If the content encoding type is not recognized, no effort will be made to do character set
// conversion.
func (p *Part) buildContentReaders(r io.Reader) error {
	// Read raw content into buffer
	buf := new(bytes.Buffer)
	if _, err := buf.ReadFrom(r); err != nil {
		return err
	}

	var contentReader io.Reader = buf
	valid := true

	// Raw content reader
	p.rawReader = contentReader

	// Build content decoding reader
	encoding := p.Header.Get(hnContentEncoding)
	switch strings.ToLower(encoding) {
	case "quoted-printable":
		contentReader = newQPCleaner(contentReader)
		contentReader = quotedprintable.NewReader(contentReader)
	case "base64":
		contentReader = newBase64Cleaner(contentReader)
		contentReader = base64.NewDecoder(base64.StdEncoding, contentReader)
	case "8bit", "7bit", "binary", "":
		// No decoding required
	default:
		// Unknown encoding
		valid = false
		p.addWarning(
			errorContentEncoding,
			"Unrecognized Content-Transfer-Encoding type %q",
			encoding)
	}
	p.decodedReader = contentReader

	if valid {
		// decodedReader is good; build character set conversion reader
		if p.Charset != "" {
			if reader, err := newCharsetReader(p.Charset, contentReader); err == nil {
				contentReader = reader
			} else {
				// Try to parse charset again here to see if we can salvage some badly formed ones
				// like charset="charset=utf-8"
				charsetp := strings.Split(p.Charset, "=")
				if strings.ToLower(charsetp[0]) == "charset" && len(charsetp) > 1 {
					p.Charset = charsetp[1]
					if reader, err := newCharsetReader(p.Charset, contentReader); err == nil {
						contentReader = reader
					} else {
						// Failed to get a conversion reader
						p.addWarning(errorCharsetConversion, err.Error())
					}
				} else {
					// Failed to get a conversion reader
					p.addWarning(errorCharsetConversion, err.Error())
				}
			}
		}
	}
	p.utf8Reader = contentReader
	return nil
}

// ReadParts reads a MIME document from the provided reader and parses it into tree of Part objects.
func ReadParts(r io.Reader) (*Part, error) {
	br := bufio.NewReader(r)
	root := &Part{}

	// Read header
	header, err := readHeader(br, root)
	if err != nil {
		return nil, err
	}
	root.Header = header

	// Content-Type
	contentType := header.Get(hnContentType)
	if contentType == "" {
		root.addWarning(
			errorMissingContentType,
			"MIME parts should have a Content-Type header")
	}
	mediatype, params, err := parseMediaType(header.Get(hnContentType))
	if contentType != "" && err != nil {
		return nil, err
	}
	root.ContentType = mediatype
	root.Charset = params[hpCharset]

	if strings.HasPrefix(mediatype, ctMultipartPrefix) {
		// Content is multipart, parse it
		boundary := params[hpBoundary]
		err = parseParts(root, br, boundary)
		if err != nil {
			return nil, err
		}
	} else {
		// Content is text or data, build content reader pipeline
		if err := root.buildContentReaders(br); err != nil {
			return nil, err
		}
	}

	return root, nil
}

func parseMediaType(ctype string) (string, map[string]string, error) {
	// Parse Content-Type header
	mtype, mparams, err := mime.ParseMediaType(ctype)
	if err != nil {
		// Small hack to remove harmless charset duplicate params
		mctype := parseBadContentType(ctype, ";")
		mtype, mparams, err = mime.ParseMediaType(mctype)
		if err != nil {
			// Some badly formed content-types forget to send a ; between fields
			mctype := parseBadContentType(ctype, " ")
			if strings.Contains(mctype, `name=""`) {
				mctype = strings.Replace(mctype, `name=""`, `name=" "`, -1)
			}
			mtype, mparams, err = mime.ParseMediaType(mctype)
			if err != nil {
				return "", make(map[string]string), err
			}
		}
	}
	return mtype, mparams, err
}

func parseBadContentType(ctype, sep string) string {
	cp := strings.Split(ctype, sep)
	mctype := ""
	for _, p := range cp {
		if strings.Contains(p, "=") {
			params := strings.Split(p, "=")
			if !strings.Contains(mctype, params[0]+"=") {
				mctype += p + ";"
			}
		} else {
			mctype += p + ";"
		}
	}
	return mctype
}

// parseParts recursively parses a mime multipart document.
func parseParts(parent *Part, reader *bufio.Reader, boundary string) error {
	var prevSibling *Part

	// Loop over MIME parts
	br := newBoundaryReader(reader, boundary)
	for {
		next, err := br.Next()
		if err != nil && err != io.EOF {
			return err
		}
		if !next {
			break
		}
		p := &Part{Parent: parent}
		bbr := bufio.NewReader(br)
		header, err := readHeader(bbr, p)
		p.Header = header
		if err == errEmptyHeaderBlock {
			// Empty header probably means the part didn't use the correct trailing "--" syntax to
			// close its boundary.
			if next, err = br.Next(); err != nil {
				if err == io.EOF || strings.HasSuffix(err.Error(), "EOF") {
					// There are no more Parts, but the error belongs to a sibling or parent,
					// because this Part doesn't actually exist.
					owner := parent
					if prevSibling != nil {
						owner = prevSibling
					}
					owner.addWarning(
						errorMissingBoundary,
						"Boundary %q was not closed correctly",
						boundary)
					break
				}
				return fmt.Errorf("Error at boundary %v: %v", boundary, err)
			}
		} else if err != nil {
			return err
		}

		ctype := header.Get(hnContentType)
		if ctype == "" {
			p.addWarning(
				errorMissingContentType,
				"MIME parts should have a Content-Type header")
		} else {
			// Parse Content-Type header
			mtype, mparams, err := parseMediaType(ctype)
			if err != nil {
				return err
			}
			p.ContentType = mtype

			// Set disposition, filename, charset if available
			p.setupContentHeaders(mparams)
			p.boundary = mparams[hpBoundary]
		}

		// Insert this Part into the MIME tree
		if prevSibling != nil {
			prevSibling.NextSibling = p
		} else {
			parent.FirstChild = p
		}
		prevSibling = p

		if p.boundary != "" {
			// Content is another multipart
			err = parseParts(p, bbr, p.boundary)
			if err != nil {
				return err
			}
		} else {
			// Content is text or data: build content reader pipeline
			if err := p.buildContentReaders(bbr); err != nil {
				return err
			}
		}
	}

	return nil
}
<commit_msg>Add Unique ID's to Envelope's Parts (#35)<commit_after>package enmime

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"fmt"
	"io"
	"mime"
	"mime/quotedprintable"
	"net/textproto"
	"strconv"
	"strings"
)

// Part represents a node in the MIME multipart tree.  The Content-Type, Disposition and File Name
// are parsed out of the header for easier access.
type Part struct {
	Header      textproto.MIMEHeader // Header for this Part
	Parent      *Part                // Parent of this part (can be nil)
	FirstChild  *Part                // FirstChild is the top most child of this part
	NextSibling *Part                // NextSibling of this part
	ContentType string               // ContentType header without parameters
	Disposition string               // Content-Disposition header without parameters
	FileName    string               // The file-name from disposition or type header
	Charset     string               // The content charset encoding label
	Errors      []Error              // Errors encountered while parsing this part
	PartID      string               // The ID representing the part's exact position within the MIME Part Tree

	boundary      string    // Boundary marker used within this part
	rawReader     io.Reader // The raw Part content, no decoding or charset conversion
	decodedReader io.Reader // The content decoded from quoted-printable or base64
	utf8Reader    io.Reader // The decoded content converted to UTF-8
}

// NewPart creates a new Part object.  It does not update the parents FirstChild attribute.
func NewPart(parent *Part, contentType string) *Part {
	return &Part{Parent: parent, ContentType: contentType}
}

// Read returns the decoded & UTF-8 converted content; implements io.Reader.
func (p *Part) Read(b []byte) (n int, err error) {
	if p.utf8Reader == nil {
		return 0, io.EOF
	}
	return p.utf8Reader.Read(b)
}

// setupContentHeaders uses Content-Type media params and Content-Disposition headers to populate
// the disposition, filename, and charset fields.
func (p *Part) setupContentHeaders(mediaParams map[string]string) {
	// Determine content disposition, filename, character set
	disposition, dparams, err := parseMediaType(p.Header.Get(hnContentDisposition))
	if err == nil {
		// Disposition is optional
		p.Disposition = disposition
		p.FileName = decodeHeader(dparams[hpFilename])
	}
	if p.FileName == "" && mediaParams[hpName] != "" {
		p.FileName = decodeHeader(mediaParams[hpName])
	}
	if p.FileName == "" && mediaParams[hpFile] != "" {
		p.FileName = decodeHeader(mediaParams[hpFile])
	}
	if p.Charset == "" {
		p.Charset = mediaParams[hpCharset]
	}
}

// buildContentReaders sets up the decodedReader and utf8Reader based on the Part headers.  If no
// translation is required at a particular stage, the reader will be the same as its predecessor.
// If the content encoding type is not recognized, no effort will be made to do character set
// conversion.
func (p *Part) buildContentReaders(r io.Reader) error {
	// Read raw content into buffer
	buf := new(bytes.Buffer)
	if _, err := buf.ReadFrom(r); err != nil {
		return err
	}

	var contentReader io.Reader = buf
	valid := true

	// Raw content reader
	p.rawReader = contentReader

	// Build content decoding reader
	encoding := p.Header.Get(hnContentEncoding)
	switch strings.ToLower(encoding) {
	case "quoted-printable":
		contentReader = newQPCleaner(contentReader)
		contentReader = quotedprintable.NewReader(contentReader)
	case "base64":
		contentReader = newBase64Cleaner(contentReader)
		contentReader = base64.NewDecoder(base64.StdEncoding, contentReader)
	case "8bit", "7bit", "binary", "":
		// No decoding required
	default:
		// Unknown encoding
		valid = false
		p.addWarning(
			errorContentEncoding,
			"Unrecognized Content-Transfer-Encoding type %q",
			encoding)
	}
	p.decodedReader = contentReader

	if valid {
		// decodedReader is good; build character set conversion reader
		if p.Charset != "" {
			if reader, err := newCharsetReader(p.Charset, contentReader); err == nil {
				contentReader = reader
			} else {
				// Try to parse charset again here to see if we can salvage some badly formed ones
				// like charset="charset=utf-8"
				charsetp := strings.Split(p.Charset, "=")
				if strings.ToLower(charsetp[0]) == "charset" && len(charsetp) > 1 {
					p.Charset = charsetp[1]
					if reader, err := newCharsetReader(p.Charset, contentReader); err == nil {
						contentReader = reader
					} else {
						// Failed to get a conversion reader
						p.addWarning(errorCharsetConversion, err.Error())
					}
				} else {
					// Failed to get a conversion reader
					p.addWarning(errorCharsetConversion, err.Error())
				}
			}
		}
	}
	p.utf8Reader = contentReader
	return nil
}

// ReadParts reads a MIME document from the provided reader and parses it into tree of Part objects.
func ReadParts(r io.Reader) (*Part, error) {
	br := bufio.NewReader(r)
	root := &Part{}

	// Read header
	header, err := readHeader(br, root)
	if err != nil {
		return nil, err
	}
	root.Header = header

	// Content-Type
	contentType := header.Get(hnContentType)
	if contentType == "" {
		root.addWarning(
			errorMissingContentType,
			"MIME parts should have a Content-Type header")
	}
	mediatype, params, err := parseMediaType(header.Get(hnContentType))
	if contentType != "" && err != nil {
		return nil, err
	}
	root.ContentType = mediatype
	root.Charset = params[hpCharset]

	if strings.HasPrefix(mediatype, ctMultipartPrefix) {
		// Content is multipart, parse it
		boundary := params[hpBoundary]
		err = parseParts(root, br, boundary)
		if err != nil {
			return nil, err
		}
	} else {
		// Content is text or data, build content reader pipeline
		if err := root.buildContentReaders(br); err != nil {
			return nil, err
		}
	}

	return root, nil
}

func parseMediaType(ctype string) (string, map[string]string, error) {
	// Parse Content-Type header
	mtype, mparams, err := mime.ParseMediaType(ctype)
	if err != nil {
		// Small hack to remove harmless charset duplicate params
		mctype := parseBadContentType(ctype, ";")
		mtype, mparams, err = mime.ParseMediaType(mctype)
		if err != nil {
			// Some badly formed content-types forget to send a ; between fields
			mctype := parseBadContentType(ctype, " ")
			if strings.Contains(mctype, `name=""`) {
				mctype = strings.Replace(mctype, `name=""`, `name=" "`, -1)
			}
			mtype, mparams, err = mime.ParseMediaType(mctype)
			if err != nil {
				return "", make(map[string]string), err
			}
		}
	}
	return mtype, mparams, err
}

func parseBadContentType(ctype, sep string) string {
	cp := strings.Split(ctype, sep)
	mctype := ""
	for _, p := range cp {
		if strings.Contains(p, "=") {
			params := strings.Split(p, "=")
			if !strings.Contains(mctype, params[0]+"=") {
				mctype += p + ";"
			}
		} else {
			mctype += p + ";"
		}
	}
	return mctype
}

// parseParts recursively parses a mime multipart document and sets each Part's PartID.
func parseParts(parent *Part, reader *bufio.Reader, boundary string) error {
	var prevSibling *Part

	firstRecursion := parent.Parent == nil
	// e.Root.PartID = 0
	if firstRecursion {
		parent.PartID = "0"
	}

	var indexPartID int = 0

	// Loop over MIME parts
	br := newBoundaryReader(reader, boundary)
	for {

		indexPartID++

		next, err := br.Next()
		if err != nil && err != io.EOF {
			return err
		}
		if !next {
			break
		}
		p := &Part{Parent: parent}

		// Set this Part's PartID, indicating its position within the MIME Part Tree
		if firstRecursion {
			p.PartID = strconv.Itoa(indexPartID)
		} else {
			p.PartID = p.Parent.PartID + "." + strconv.Itoa(indexPartID)
		}

		bbr := bufio.NewReader(br)
		header, err := readHeader(bbr, p)
		p.Header = header
		if err == errEmptyHeaderBlock {
			// Empty header probably means the part didn't use the correct trailing "--" syntax to
			// close its boundary.
			if next, err = br.Next(); err != nil {
				if err == io.EOF || strings.HasSuffix(err.Error(), "EOF") {
					// There are no more Parts, but the error belongs to a sibling or parent,
					// because this Part doesn't actually exist.
					owner := parent
					if prevSibling != nil {
						owner = prevSibling
					}
					owner.addWarning(
						errorMissingBoundary,
						"Boundary %q was not closed correctly",
						boundary)
					break
				}
				return fmt.Errorf("Error at boundary %v: %v", boundary, err)
			}
		} else if err != nil {
			return err
		}

		ctype := header.Get(hnContentType)
		if ctype == "" {
			p.addWarning(
				errorMissingContentType,
				"MIME parts should have a Content-Type header")
		} else {
			// Parse Content-Type header
			mtype, mparams, err := parseMediaType(ctype)
			if err != nil {
				return err
			}
			p.ContentType = mtype

			// Set disposition, filename, charset if available
			p.setupContentHeaders(mparams)
			p.boundary = mparams[hpBoundary]
		}

		// Insert this Part into the MIME tree
		if prevSibling != nil {
			prevSibling.NextSibling = p
		} else {
			parent.FirstChild = p
		}
		prevSibling = p

		if p.boundary != "" {
			// Content is another multipart
			err = parseParts(p, bbr, p.boundary)
			if err != nil {
				return err
			}
		} else {
			// Content is text or data: build content reader pipeline
			if err := p.buildContentReaders(bbr); err != nil {
				return err
			}
		}
	}

	// If a Part is "multipart/" Content-Type, it will have .0 appended to its PartID
	// i.e. it is the root of its MIME Part subtree
	if !firstRecursion {
		parent.PartID += ".0"
	}

	return nil
}
<|endoftext|>


<commit_before>package rbuf

// copyright (c) 2016, Jason E. Aten
// license: MIT

import "io"

// PointerRingBuf:
//
//  a fixed-size circular ring buffer of interface{}
//
type PointerRingBuf struct {
	A        []interface{}
	N        int // MaxView, the total size of A, whether or not in use.
	Beg      int // start of in-use data in A
	Readable int // number of pointers available in A (in use)
}

// constructor. NewPointerRingBuf will allocate internally
// a slice of size maxViewInBytes.
func NewPointerRingBuf(maxViewInBytes int) *PointerRingBuf {
	n := maxViewInBytes
	r := &PointerRingBuf{
		N:        n,
		Beg:      0,
		Readable: 0,
	}
	r.A = make([]interface{}, n, n)

	return r
}

// TwoContig returns all readable pointers, but in two separate slices,
// to avoid copying. The two slices are from the same buffer, but
// are not contiguous. Either or both may be empty slices.
func (b *PointerRingBuf) TwoContig(makeCopy bool) (first []interface{}, second []interface{}) {

	extent := b.Beg + b.Readable
	if extent <= b.N {
		// we fit contiguously in this buffer without wrapping to the other.
		// Let second stay an empty slice.
		return b.A[b.Beg:(b.Beg + b.Readable)], second
	}

	return b.A[b.Beg:(b.Beg + b.Readable)], b.A[0:(extent % b.N)]
}

// ReadPtrs():
//
// from bytes.Buffer.Read(): Read reads the next len(p) interface{}
// pointers from the buffer or until the buffer is drained. The return
// value n is the number of bytes read. If the buffer has no data
// to return, err is io.EOF (unless len(p) is zero); otherwise it is nil.
func (b *PointerRingBuf) ReadPtrs(p []interface{}) (n int, err error) {
	return b.readAndMaybeAdvance(p, true)
}

// ReadWithoutAdvance(): if you want to Read the data and leave
// it in the buffer, so as to peek ahead for example.
func (b *PointerRingBuf) ReadWithoutAdvance(p []interface{}) (n int, err error) {
	return b.readAndMaybeAdvance(p, false)
}

func (b *PointerRingBuf) readAndMaybeAdvance(p []interface{}, doAdvance bool) (n int, err error) {
	if len(p) == 0 {
		return 0, nil
	}
	if b.Readable == 0 {
		return 0, io.EOF
	}
	extent := b.Beg + b.Readable
	if extent <= b.N {
		n += copy(p, b.A[b.Beg:extent])
	} else {
		n += copy(p, b.A[b.Beg:b.N])
		if n < len(p) {
			n += copy(p[n:], b.A[0:(extent%b.N)])
		}
	}
	if doAdvance {
		b.Advance(n)
	}
	return
}

//
// WritePtrs writes len(p) interface{} values from p to
// the underlying data stream.
// It returns the number of bytes written from p (0 <= n <= len(p))
// and any error encountered that caused the write to stop early.
// Write must return a non-nil error if it returns n < len(p).
//
func (b *PointerRingBuf) WritePtrs(p []interface{}) (n int, err error) {
	for {
		if len(p) == 0 {
			// nothing (left) to copy in; notice we shorten our
			// local copy p (below) as we read from it.
			return
		}

		writeCapacity := b.N - b.Readable
		if writeCapacity <= 0 {
			// we are all full up already.
			return n, io.ErrShortWrite
		}
		if len(p) > writeCapacity {
			err = io.ErrShortWrite
			// leave err set and
			// keep going, write what we can.
		}

		writeStart := (b.Beg + b.Readable) % b.N

		upperLim := intMin(writeStart+writeCapacity, b.N)

		k := copy(b.A[writeStart:upperLim], p)

		n += k
		b.Readable += k
		p = p[k:]

		// we can fill from b.A[0:something] from
		// p's remainder, so loop
	}
}

// Reset quickly forgets any data stored in the ring buffer. The
// data is still there, but the ring buffer will ignore it and
// overwrite those buffers as new data comes in.
func (b *PointerRingBuf) Reset() {
	b.Beg = 0
	b.Readable = 0
}

// Advance(): non-standard, but better than Next(),
// because we don't have to unwrap our buffer and pay the cpu time
// for the copy that unwrapping may need.
// Useful in conjuction/after ReadWithoutAdvance() above.
func (b *PointerRingBuf) Advance(n int) {
	if n <= 0 {
		return
	}
	if n > b.Readable {
		n = b.Readable
	}
	b.Readable -= n
	b.Beg = (b.Beg + n) % b.N
}

// Adopt(): non-standard.
//
// For efficiency's sake, (possibly) take ownership of
// already allocated slice offered in me.
//
// If me is large we will adopt it, and we will potentially then
// write to the me buffer.
// If we already have a bigger buffer, copy me into the existing
// buffer instead.
func (b *PointerRingBuf) Adopt(me []interface{}) {
	n := len(me)
	if n > b.N {
		b.A = me
		b.N = n
		b.Beg = 0
		b.Readable = n
	} else {
		// we already have a larger buffer, reuse it.
		copy(b.A, me)
		b.Beg = 0
		b.Readable = n
	}
}
<commit_msg>pbuf fix<commit_after>package rbuf

// copyright (c) 2016, Jason E. Aten
// license: MIT

import "io"

// PointerRingBuf:
//
//  a fixed-size circular ring buffer of interface{}
//
type PointerRingBuf struct {
	A        []interface{}
	N        int // MaxView, the total size of A, whether or not in use.
	Beg      int // start of in-use data in A
	Readable int // number of pointers available in A (in use)
}

// constructor. NewPointerRingBuf will allocate internally
// a slice of size maxViewInBytes.
func NewPointerRingBuf(maxViewInBytes int) *PointerRingBuf {
	n := maxViewInBytes
	r := &PointerRingBuf{
		N:        n,
		Beg:      0,
		Readable: 0,
	}
	r.A = make([]interface{}, n, n)

	return r
}

// TwoContig returns all readable pointers, but in two separate slices,
// to avoid copying. The two slices are from the same buffer, but
// are not contiguous. Either or both may be empty slices.
func (b *PointerRingBuf) TwoContig(makeCopy bool) (first []interface{}, second []interface{}) {

	extent := b.Beg + b.Readable
	if extent <= b.N {
		// we fit contiguously in this buffer without wrapping to the other.
		// Let second stay an empty slice.
		return b.A[b.Beg:(b.Beg + b.Readable)], second
	}

	return b.A[b.Beg:b.N], b.A[0:(extent % b.N)]
}

// ReadPtrs():
//
// from bytes.Buffer.Read(): Read reads the next len(p) interface{}
// pointers from the buffer or until the buffer is drained. The return
// value n is the number of bytes read. If the buffer has no data
// to return, err is io.EOF (unless len(p) is zero); otherwise it is nil.
func (b *PointerRingBuf) ReadPtrs(p []interface{}) (n int, err error) {
	return b.readAndMaybeAdvance(p, true)
}

// ReadWithoutAdvance(): if you want to Read the data and leave
// it in the buffer, so as to peek ahead for example.
func (b *PointerRingBuf) ReadWithoutAdvance(p []interface{}) (n int, err error) {
	return b.readAndMaybeAdvance(p, false)
}

func (b *PointerRingBuf) readAndMaybeAdvance(p []interface{}, doAdvance bool) (n int, err error) {
	if len(p) == 0 {
		return 0, nil
	}
	if b.Readable == 0 {
		return 0, io.EOF
	}
	extent := b.Beg + b.Readable
	if extent <= b.N {
		n += copy(p, b.A[b.Beg:extent])
	} else {
		n += copy(p, b.A[b.Beg:b.N])
		if n < len(p) {
			n += copy(p[n:], b.A[0:(extent%b.N)])
		}
	}
	if doAdvance {
		b.Advance(n)
	}
	return
}

//
// WritePtrs writes len(p) interface{} values from p to
// the underlying data stream.
// It returns the number of bytes written from p (0 <= n <= len(p))
// and any error encountered that caused the write to stop early.
// Write must return a non-nil error if it returns n < len(p).
//
func (b *PointerRingBuf) WritePtrs(p []interface{}) (n int, err error) {
	for {
		if len(p) == 0 {
			// nothing (left) to copy in; notice we shorten our
			// local copy p (below) as we read from it.
			return
		}

		writeCapacity := b.N - b.Readable
		if writeCapacity <= 0 {
			// we are all full up already.
			return n, io.ErrShortWrite
		}
		if len(p) > writeCapacity {
			err = io.ErrShortWrite
			// leave err set and
			// keep going, write what we can.
		}

		writeStart := (b.Beg + b.Readable) % b.N

		upperLim := intMin(writeStart+writeCapacity, b.N)

		k := copy(b.A[writeStart:upperLim], p)

		n += k
		b.Readable += k
		p = p[k:]

		// we can fill from b.A[0:something] from
		// p's remainder, so loop
	}
}

// Reset quickly forgets any data stored in the ring buffer. The
// data is still there, but the ring buffer will ignore it and
// overwrite those buffers as new data comes in.
func (b *PointerRingBuf) Reset() {
	b.Beg = 0
	b.Readable = 0
}

// Advance(): non-standard, but better than Next(),
// because we don't have to unwrap our buffer and pay the cpu time
// for the copy that unwrapping may need.
// Useful in conjuction/after ReadWithoutAdvance() above.
func (b *PointerRingBuf) Advance(n int) {
	if n <= 0 {
		return
	}
	if n > b.Readable {
		n = b.Readable
	}
	b.Readable -= n
	b.Beg = (b.Beg + n) % b.N
}

// Adopt(): non-standard.
//
// For efficiency's sake, (possibly) take ownership of
// already allocated slice offered in me.
//
// If me is large we will adopt it, and we will potentially then
// write to the me buffer.
// If we already have a bigger buffer, copy me into the existing
// buffer instead.
func (b *PointerRingBuf) Adopt(me []interface{}) {
	n := len(me)
	if n > b.N {
		b.A = me
		b.N = n
		b.Beg = 0
		b.Readable = n
	} else {
		// we already have a larger buffer, reuse it.
		copy(b.A, me)
		b.Beg = 0
		b.Readable = n
	}
}
<|endoftext|>