<commit_before>package msgpack

import (
	"bytes"
	"fmt"
	"reflect"
	"sync"

	"gopkg.in/vmihailenco/msgpack.v2/codes"
)

var (
	extTypes [128]reflect.Type
)

var bufferPool = &sync.Pool{
	New: func() interface{} {
		return &bytes.Buffer{}
	},
}

func RegisterExt(id int8, value interface{}) {
	if extTypes[id] != nil {
		panic(fmt.Errorf("ext with id %d is already registered", id))
	}
	extTypes[id] = reflect.TypeOf(value)
}

func extTypeId(typ reflect.Type) int8 {
	for id, t := range extTypes {
		if t == typ {
			return int8(id)
		}
	}
	return -1
}

func makeExtEncoder(id int8, enc encoderFunc) encoderFunc {
	return func(e *Encoder, v reflect.Value) error {
		buf := bufferPool.Get().(*bytes.Buffer)
		defer bufferPool.Put(buf)

		oldw := e.w
		e.w = buf
		err := enc(e, v)
		e.w = oldw

		if err != nil {
			return err
		}

		if err := e.encodeExtLen(buf.Len()); err != nil {
			return err
		}
		if err := e.w.WriteByte(byte(id)); err != nil {
			return err
		}
		return e.write(buf.Bytes())
	}
}

func (e *Encoder) encodeExtLen(l int) error {
	switch {
	case l == 1:
		return e.w.WriteByte(codes.FixExt1)
	case l == 2:
		return e.w.WriteByte(codes.FixExt2)
	case l == 4:
		return e.w.WriteByte(codes.FixExt4)
	case l == 8:
		return e.w.WriteByte(codes.FixExt8)
	case l == 16:
		return e.w.WriteByte(codes.FixExt16)
	case l < 256:
		return e.write1(codes.Ext8, uint64(l))
	case l < 65536:
		return e.write2(codes.Ext16, uint64(l))
	default:
		return e.write4(codes.Ext32, uint64(l))
	}
}

func (d *Decoder) decodeExtLen() (int, error) {
	c, err := d.r.ReadByte()
	if err != nil {
		return 0, err
	}
	switch c {
	case codes.FixExt1:
		return 1, nil
	case codes.FixExt2:
		return 2, nil
	case codes.FixExt4:
		return 4, nil
	case codes.FixExt8:
		return 8, nil
	case codes.FixExt16:
		return 16, nil
	case codes.Ext8:
		n, err := d.uint8()
		return int(n), err
	case codes.Ext16:
		n, err := d.uint16()
		return int(n), err
	case codes.Ext32:
		n, err := d.uint32()
		return int(n), err
	default:
		return 0, fmt.Errorf("msgpack: invalid code %x decoding ext length", c)
	}
}

func (d *Decoder) decodeExt() (interface{}, error) {
	// TODO: use decoded length.
	_, err := d.decodeExtLen()
	if err != nil {
		return nil, err
	}
	extId, err := d.r.ReadByte()
	if err != nil {
		return nil, err
	}
	typ := extTypes[extId]
	if typ == nil {
		return nil, fmt.Errorf("msgpack: unregistered ext id %d", extId)
	}
	v := reflect.New(typ).Elem()
	if err := d.DecodeValue(v); err != nil {
		return nil, err
	}
	return v.Interface(), nil
}
<commit_msg>Reset buffer before reusing.<commit_after>package msgpack

import (
	"bytes"
	"fmt"
	"reflect"
	"sync"

	"gopkg.in/vmihailenco/msgpack.v2/codes"
)

var (
	extTypes [128]reflect.Type
)

var bufferPool = &sync.Pool{
	New: func() interface{} {
		return &bytes.Buffer{}
	},
}

func RegisterExt(id int8, value interface{}) {
	if extTypes[id] != nil {
		panic(fmt.Errorf("ext with id %d is already registered", id))
	}
	extTypes[id] = reflect.TypeOf(value)
}

func extTypeId(typ reflect.Type) int8 {
	for id, t := range extTypes {
		if t == typ {
			return int8(id)
		}
	}
	return -1
}

func makeExtEncoder(id int8, enc encoderFunc) encoderFunc {
	return func(e *Encoder, v reflect.Value) error {
		buf := bufferPool.Get().(*bytes.Buffer)
		defer bufferPool.Put(buf)
		buf.Reset()

		oldw := e.w
		e.w = buf
		err := enc(e, v)
		e.w = oldw

		if err != nil {
			return err
		}

		if err := e.encodeExtLen(buf.Len()); err != nil {
			return err
		}
		if err := e.w.WriteByte(byte(id)); err != nil {
			return err
		}
		return e.write(buf.Bytes())
	}
}

func (e *Encoder) encodeExtLen(l int) error {
	switch {
	case l == 1:
		return e.w.WriteByte(codes.FixExt1)
	case l == 2:
		return e.w.WriteByte(codes.FixExt2)
	case l == 4:
		return e.w.WriteByte(codes.FixExt4)
	case l == 8:
		return e.w.WriteByte(codes.FixExt8)
	case l == 16:
		return e.w.WriteByte(codes.FixExt16)
	case l < 256:
		return e.write1(codes.Ext8, uint64(l))
	case l < 65536:
		return e.write2(codes.Ext16, uint64(l))
	default:
		return e.write4(codes.Ext32, uint64(l))
	}
}

func (d *Decoder) decodeExtLen() (int, error) {
	c, err := d.r.ReadByte()
	if err != nil {
		return 0, err
	}
	switch c {
	case codes.FixExt1:
		return 1, nil
	case codes.FixExt2:
		return 2, nil
	case codes.FixExt4:
		return 4, nil
	case codes.FixExt8:
		return 8, nil
	case codes.FixExt16:
		return 16, nil
	case codes.Ext8:
		n, err := d.uint8()
		return int(n), err
	case codes.Ext16:
		n, err := d.uint16()
		return int(n), err
	case codes.Ext32:
		n, err := d.uint32()
		return int(n), err
	default:
		return 0, fmt.Errorf("msgpack: invalid code %x decoding ext length", c)
	}
}

func (d *Decoder) decodeExt() (interface{}, error) {
	// TODO: use decoded length.
	_, err := d.decodeExtLen()
	if err != nil {
		return nil, err
	}
	extId, err := d.r.ReadByte()
	if err != nil {
		return nil, err
	}
	typ := extTypes[extId]
	if typ == nil {
		return nil, fmt.Errorf("msgpack: unregistered ext id %d", extId)
	}
	v := reflect.New(typ).Elem()
	if err := d.DecodeValue(v); err != nil {
		return nil, err
	}
	return v.Interface(), nil
}
<|endoftext|>


<commit_before>package httputilmore

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"os"
	"regexp"
	"strings"

	"github.com/grokify/gotilla/strconv/strconvutil"
)

const (
	HeaderAuthorization                = "Authorization"
	HeaderContentDisposition           = "Content-Disposition"
	HeaderContentLength                = "Content-Length"
	HeaderContentTransferEncoding      = "Content-Transfer-Encoding"
	HeaderContentType                  = "Content-Type"
	HeaderLocation                     = "Location"
	HeaderUserAgent                    = "User-Agent"
	HeaderXContentTypeOptions          = "X-Content-Type-Options"
	ContentTypeAppJsonUtf8             = "application/json; charset=utf-8"
	ContentTypeAppFormUrlEncoded       = "application/x-www-form-urlencoded"
	ContentTypeTextCalendarUtf8Request = `text/calendar; charset="utf-8"; method=REQUEST`
	ContentTypeTextHtmlUtf8            = "text/html; charset=utf-8"
	ContentTypeTextPlainUsAscii        = "text/plain; charset=us-ascii"
	ContentTypeTextPlainUtf8           = "text/plain; charset=utf-8"
	SchemeHTTPS                        = "https"
)

// GetWriteFile performs a HTTP GET request and saves the response body
// to the file path specified
func GetWriteFile(url string, filename string, perm os.FileMode) ([]byte, error) {
	_, bytes, err := GetResponseAndBytes(url)
	if err != nil {
		return bytes, err
	}
	err = ioutil.WriteFile(filename, bytes, perm)
	return bytes, err
}

// ResponseBody returns the body as a byte array
func ResponseBody(res *http.Response) ([]byte, error) {
	defer res.Body.Close()
	contents, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return []byte{}, err
	}
	return contents, nil
}

// ResponseBodyJSONMapIndent returns the body as a generic JSON dictionary
func ResponseBodyJSONMapIndent(res *http.Response, prefix string, indent string) ([]byte, error) {
	body, err := ResponseBody(res)
	if err != nil {
		return body, err
	}
	any := map[string]interface{}{}
	json.Unmarshal(body, &any)
	return json.MarshalIndent(any, prefix, indent)
}

// GetResponseAndBytes retreives a URL and returns the response body
// as a byte array in addition to the *http.Response.
func GetResponseAndBytes(url string) (*http.Response, []byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return resp, []byte{}, err
	}
	bytes, err := ResponseBody(resp)
	return resp, bytes, err
}

// UnmarshalResponseJSON unmarshal a `*http.Response` JSON body into
// a data pointer.
func UnmarshalResponseJSON(resp *http.Response, data interface{}) error {
	//bytes, err := ResponseBody(resp)
	bytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	return json.Unmarshal(bytes, data)
}

// PrintRequestOut prints a http.Request using `httputil.DumpRequestOut`.
func PrintRequestOut(req *http.Request, includeBody bool) error {
	reqBytes, err := httputil.DumpRequestOut(req, includeBody)
	if err != nil {
		return err
	}
	fmt.Println(string(reqBytes))
	return nil
}

// PrintResponse prints a http.Response using `httputil.DumpResponse`.
func PrintResponse(resp *http.Response, includeBody bool) error {
	respBytes, err := httputil.DumpResponse(resp, includeBody)
	if err != nil {
		return err
	}
	fmt.Println(string(respBytes))
	return nil
}

// MergeHeader merges two http.Header adding the values of the second
// to the first.
func MergeHeader(base, extra http.Header, overwrite bool) http.Header {
	for k, vals := range extra {
		if overwrite {
			base.Del(k)
		}

		for _, v := range vals {
			v = strings.TrimSpace(v)
			if len(v) > 0 {
				base.Add(k, v)
			}
		}
	}
	return base
}

func ParseMultipartFormDataBoundaryFromHeader(contentType string) string {
	rx := regexp.MustCompile(`^multipart/form-data.+boundary="?([^;"]+)`)
	m := rx.FindStringSubmatch(contentType)
	if len(m) > 0 {
		return m[1]
	}
	return ""
}

// RateLimitInfo is a structure for holding parsed rate limit info.
// It uses headers from the GitHub, RingCentral and Twitter APIs.
type RateLimitInfo struct {
	StatusCode          int
	RetryAfter          int
	XRateLimitLimit     int
	XRateLimitRemaining int
	XRateLimitReset     int
	XRateLimitWindow    int
}

// NewResponseRateLimitInfo returns a RateLimitInfo from a http.Response.
func NewResponseRateLimitInfo(resp *http.Response, useXrlHyphen bool) RateLimitInfo {
	rlstat := RateLimitInfo{
		StatusCode: resp.StatusCode,
		RetryAfter: strconvutil.AtoiWithDefault(resp.Header.Get("Retry-After"), 0)}

	if useXrlHyphen {
		rlstat.XRateLimitLimit = strconvutil.AtoiWithDefault(resp.Header.Get("X-Rate-Limit-Limit"), 0)
		rlstat.XRateLimitRemaining = strconvutil.AtoiWithDefault(resp.Header.Get("X-Rate-Limit-Remaining"), 0)
		rlstat.XRateLimitReset = strconvutil.AtoiWithDefault(resp.Header.Get("X-Rate-Limit-Reset"), 0)
		rlstat.XRateLimitWindow = strconvutil.AtoiWithDefault(resp.Header.Get("X-Rate-Limit-Window"), 0)
	} else {
		rlstat.XRateLimitLimit = strconvutil.AtoiWithDefault(resp.Header.Get("X-RateLimit-Limit"), 0)
		rlstat.XRateLimitRemaining = strconvutil.AtoiWithDefault(resp.Header.Get("X-RateLimit-Remaining"), 0)
		rlstat.XRateLimitReset = strconvutil.AtoiWithDefault(resp.Header.Get("X-RateLimit-Reset"), 0)
		rlstat.XRateLimitWindow = strconvutil.AtoiWithDefault(resp.Header.Get("X-RateLimit-Window"), 0)
	}
	return rlstat
}

type FnLogRateLimitInfo func(RateLimitInfo)
<commit_msg>add httputilmore.PostJsonSimple<commit_after>package httputilmore

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"os"
	"regexp"
	"strings"

	"github.com/grokify/gotilla/strconv/strconvutil"
)

const (
	HeaderAuthorization                = "Authorization"
	HeaderContentDisposition           = "Content-Disposition"
	HeaderContentLength                = "Content-Length"
	HeaderContentTransferEncoding      = "Content-Transfer-Encoding"
	HeaderContentType                  = "Content-Type"
	HeaderLocation                     = "Location"
	HeaderUserAgent                    = "User-Agent"
	HeaderXContentTypeOptions          = "X-Content-Type-Options"
	ContentTypeAppJsonUtf8             = "application/json; charset=utf-8"
	ContentTypeAppFormUrlEncoded       = "application/x-www-form-urlencoded"
	ContentTypeTextCalendarUtf8Request = `text/calendar; charset="utf-8"; method=REQUEST`
	ContentTypeTextHtmlUtf8            = "text/html; charset=utf-8"
	ContentTypeTextPlainUsAscii        = "text/plain; charset=us-ascii"
	ContentTypeTextPlainUtf8           = "text/plain; charset=utf-8"
	SchemeHTTPS                        = "https"
)

// GetWriteFile performs a HTTP GET request and saves the response body
// to the file path specified
func GetWriteFile(url string, filename string, perm os.FileMode) ([]byte, error) {
	_, bytes, err := GetResponseAndBytes(url)
	if err != nil {
		return bytes, err
	}
	err = ioutil.WriteFile(filename, bytes, perm)
	return bytes, err
}

func PostJsonSimple(requrl string, body interface{}) (*http.Response, error) {
	bodyBytes, err := json.Marshal(body)
	if err != nil {
		return &http.Response{}, err
	}

	req, err := http.NewRequest(http.MethodPost, requrl, bytes.NewBuffer(bodyBytes))
	if err != nil {
		return &http.Response{}, err
	}
	req.Header.Set(HeaderContentType, ContentTypeAppJsonUtf8)

	client := &http.Client{}
	return client.Do(req)
}

// ResponseBody returns the body as a byte array
func ResponseBody(res *http.Response) ([]byte, error) {
	defer res.Body.Close()
	contents, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return []byte{}, err
	}
	return contents, nil
}

// ResponseBodyJSONMapIndent returns the body as a generic JSON dictionary
func ResponseBodyJSONMapIndent(res *http.Response, prefix string, indent string) ([]byte, error) {
	body, err := ResponseBody(res)
	if err != nil {
		return body, err
	}
	any := map[string]interface{}{}
	json.Unmarshal(body, &any)
	return json.MarshalIndent(any, prefix, indent)
}

// GetResponseAndBytes retreives a URL and returns the response body
// as a byte array in addition to the *http.Response.
func GetResponseAndBytes(url string) (*http.Response, []byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return resp, []byte{}, err
	}
	bytes, err := ResponseBody(resp)
	return resp, bytes, err
}

// UnmarshalResponseJSON unmarshal a `*http.Response` JSON body into
// a data pointer.
func UnmarshalResponseJSON(resp *http.Response, data interface{}) error {
	//bytes, err := ResponseBody(resp)
	bytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	return json.Unmarshal(bytes, data)
}

// PrintRequestOut prints a http.Request using `httputil.DumpRequestOut`.
func PrintRequestOut(req *http.Request, includeBody bool) error {
	reqBytes, err := httputil.DumpRequestOut(req, includeBody)
	if err != nil {
		return err
	}
	fmt.Println(string(reqBytes))
	return nil
}

// PrintResponse prints a http.Response using `httputil.DumpResponse`.
func PrintResponse(resp *http.Response, includeBody bool) error {
	respBytes, err := httputil.DumpResponse(resp, includeBody)
	if err != nil {
		return err
	}
	fmt.Println(string(respBytes))
	return nil
}

// MergeHeader merges two http.Header adding the values of the second
// to the first.
func MergeHeader(base, extra http.Header, overwrite bool) http.Header {
	for k, vals := range extra {
		if overwrite {
			base.Del(k)
		}

		for _, v := range vals {
			v = strings.TrimSpace(v)
			if len(v) > 0 {
				base.Add(k, v)
			}
		}
	}
	return base
}

func ParseMultipartFormDataBoundaryFromHeader(contentType string) string {
	rx := regexp.MustCompile(`^multipart/form-data.+boundary="?([^;"]+)`)
	m := rx.FindStringSubmatch(contentType)
	if len(m) > 0 {
		return m[1]
	}
	return ""
}

// RateLimitInfo is a structure for holding parsed rate limit info.
// It uses headers from the GitHub, RingCentral and Twitter APIs.
type RateLimitInfo struct {
	StatusCode          int
	RetryAfter          int
	XRateLimitLimit     int
	XRateLimitRemaining int
	XRateLimitReset     int
	XRateLimitWindow    int
}

// NewResponseRateLimitInfo returns a RateLimitInfo from a http.Response.
func NewResponseRateLimitInfo(resp *http.Response, useXrlHyphen bool) RateLimitInfo {
	rlstat := RateLimitInfo{
		StatusCode: resp.StatusCode,
		RetryAfter: strconvutil.AtoiWithDefault(resp.Header.Get("Retry-After"), 0)}

	if useXrlHyphen {
		rlstat.XRateLimitLimit = strconvutil.AtoiWithDefault(resp.Header.Get("X-Rate-Limit-Limit"), 0)
		rlstat.XRateLimitRemaining = strconvutil.AtoiWithDefault(resp.Header.Get("X-Rate-Limit-Remaining"), 0)
		rlstat.XRateLimitReset = strconvutil.AtoiWithDefault(resp.Header.Get("X-Rate-Limit-Reset"), 0)
		rlstat.XRateLimitWindow = strconvutil.AtoiWithDefault(resp.Header.Get("X-Rate-Limit-Window"), 0)
	} else {
		rlstat.XRateLimitLimit = strconvutil.AtoiWithDefault(resp.Header.Get("X-RateLimit-Limit"), 0)
		rlstat.XRateLimitRemaining = strconvutil.AtoiWithDefault(resp.Header.Get("X-RateLimit-Remaining"), 0)
		rlstat.XRateLimitReset = strconvutil.AtoiWithDefault(resp.Header.Get("X-RateLimit-Reset"), 0)
		rlstat.XRateLimitWindow = strconvutil.AtoiWithDefault(resp.Header.Get("X-RateLimit-Window"), 0)
	}
	return rlstat
}

type FnLogRateLimitInfo func(RateLimitInfo)
<|endoftext|>


<commit_before>package main

import (
	"strings"
	"time"

	"github.com/ninjasphere/go-hue"
	"github.com/ninjasphere/go-ninja/channels"
	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/logger"
)

var log = logger.GetLogger("hue")

func getBridge() *hue.Bridge {
	nobridge := true
	var allbridges []*hue.Bridge
	var err error
	for nobridge {
		allbridges, err = hue.FindBridgesUsingCloud()
		if err != nil {
			//log.Infof("Warning: Failed finding bridges using cloud (%s). Falling back to ssdp.", err)
			allbridges, _ = hue.FindBridges()
		}
		if len(allbridges) == 0 {
			time.Sleep(time.Second * 5) //this sucks
		} else {
			nobridge = false
			log.Infof("Found %d bridges: %s", len(allbridges), allbridges)
		}
	}
	return allbridges[0]
}

var pushButtonNotification = channels.Notification{
	Title:    "Please press the pairing button on your Philips Hue base-station",
	Subtitle: "New Hue base-station found",
	Priority: channels.NotificationPriorityDefault,
	Category: channels.NotificationCategorySuggestion,
}

func getUser(driver *HueDriver, bridge *hue.Bridge) *hue.User {
	var user *hue.User
	var err error
	noUser := true
	retries := 0
	serial := config.Serial()
	username := serial + serial //username must be long 10-40 characters
	isvaliduser, err := bridge.IsValidUser(username)
	if err != nil {
		log.Warningf("Problem determining if hue user is valid")
	}

	var notificationTime time.Time

	if isvaliduser {
		user = hue.NewUserWithBridge(username, bridge)
	} else {
		for noUser {
			user, err = bridge.CreateUser("ninjadevice", username)
			if err != nil {
				if strings.Contains(err.Error(), "101") { // there's probably a nicer way to check this
					retries++
					log.Infof("Couldn't make user, push link button. Retry: %d", retries)

					if time.Since(notificationTime) > time.Minute*5 {
						notificationTime = time.Now()
						driver.sendEvent("notification", pushButtonNotification)
					}

					time.Sleep(time.Second * 2) //this sucks

				} else {
					log.Debugf("Error creating user %s", err)
					time.Sleep(time.Second * 20)
				}
			}

			if user != nil {
				noUser = false
			}
		}
	}
	return user
}
<commit_msg>quiet, you<commit_after>package main

import (
	"strings"
	"time"

	"github.com/ninjasphere/go-hue"
	"github.com/ninjasphere/go-ninja/channels"
	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/logger"
)

var log = logger.GetLogger("hue")

func getBridge() *hue.Bridge {
	nobridge := true
	var allbridges []*hue.Bridge
	var err error
	for nobridge {
		allbridges, err = hue.FindBridgesUsingCloud()
		if err != nil {
			//log.Infof("Warning: Failed finding bridges using cloud (%s). Falling back to ssdp.", err)
			allbridges, _ = hue.FindBridges()
		}
		if len(allbridges) == 0 {
			time.Sleep(time.Second * 5) //this sucks
		} else {
			nobridge = false
			log.Infof("Found %d bridges: %s", len(allbridges), allbridges)
		}
	}
	return allbridges[0]
}

var pushButtonNotification = channels.Notification{
	Title:    "Please press the pairing button on your Philips Hue base-station",
	Subtitle: "New Hue base-station found",
	Priority: channels.NotificationPriorityDefault,
	Category: channels.NotificationCategorySuggestion,
}

func getUser(driver *HueDriver, bridge *hue.Bridge) *hue.User {
	var user *hue.User
	var err error
	noUser := true
	retries := 0
	serial := config.Serial()
	username := serial + serial //username must be long 10-40 characters
	isvaliduser, err := bridge.IsValidUser(username)
	if err != nil {
		log.Warningf("Problem determining if hue user is valid")
	}

	var notificationTime time.Time

	if isvaliduser {
		user = hue.NewUserWithBridge(username, bridge)
	} else {
		for noUser {
			user, err = bridge.CreateUser("ninjadevice", username)
			if err != nil {
				if strings.Contains(err.Error(), "101") { // there's probably a nicer way to check this
					retries++
					log.Debugf("Couldn't make user, push link button. Retry: %d", retries)

					if time.Since(notificationTime) > time.Minute*5 {
						notificationTime = time.Now()
						driver.sendEvent("notification", pushButtonNotification)
					}

					time.Sleep(time.Second * 2) //this sucks

				} else {
					log.Debugf("Error creating user %s", err)
					time.Sleep(time.Second * 20)
				}
			}

			if user != nil {
				noUser = false
			}
		}
	}
	return user
}
<|endoftext|>


<commit_before>package bsw

import "strings"

// MX returns the A record for an MX record for a domain.
func MX(domain, serverAddr string) (string, Results, error) {
	task := "mx"
	results := Results{}
	servers, err := LookupMX(domain, serverAddr)
	if err != nil {
		return task, results, err
	}
	for _, s := range servers {
		ip, err := LookupName(s, serverAddr)
		if err != nil || ip == "" {
			continue
		}
		results = append(results, Result{
			Source:   task,
			IP:       ip,
			Hostname: strings.TrimRight(s, "."),
		})
	}
	return task, results, nil
}
<commit_msg>Minor cleanup<commit_after>package bsw

import (
	"strings"
)

// MX returns the A record for any MX records for a domain.
func MX(domain, serverAddr string) (string, Results, error) {
	task := "mx"
	results := Results{}
	servers, err := LookupMX(domain, serverAddr)
	if err != nil {
		return task, results, err
	}
	for _, s := range servers {
		ip, err := LookupName(s, serverAddr)
		if err != nil || ip == "" {
			continue
		}
		results = append(results, Result{
			Source:   task,
			IP:       ip,
			Hostname: strings.TrimRight(s, "."),
		})
	}
	return task, results, nil
}
<|endoftext|>


<commit_before>package beep

import (
	"fmt"
	"time"
)

// Format is the format of a Buffer or another audio source.
type Format struct {
	// SampleRate is the number of samples per second.
	SampleRate int

	// NumChannels is the number of channels. The value of 1 is mono, the value of 2 is stereo.
	// The samples should always be interleaved.
	NumChannels int

	// Precision is the number of bytes used to encode a single sample.
	Precision int
}

// Width returns the number of bytes per one sample (all channels).
//
// This is equal to f.NumChannels * f.Precision.
func (f Format) Width() int {
	return f.NumChannels * f.Precision
}

// Duration returns the duration of n samples in this format.
func (f Format) Duration(n int) time.Duration {
	return time.Second * time.Duration(n) / time.Duration(f.SampleRate)
}

// NumSamples returns the number of samples in this format which last for d duration.
func (f Format) NumSamples(d time.Duration) int {
	return int(d * time.Duration(f.SampleRate) / time.Second)
}

// EncodeSigned encodes a single sample in f.Width() bytes to p in signed format.
func (f Format) EncodeSigned(p []byte, sample [2]float64) (n int) {
	return f.encode(true, p, sample)
}

// EncodeUnsigned encodes a single sample in f.Width() bytes to p in unsigned format.
func (f Format) EncodeUnsigned(p []byte, sample [2]float64) (n int) {
	return f.encode(false, p, sample)
}

// DecodeSigned decodes a single sample encoded in f.Width() bytes from p in signed format.
func (f Format) DecodeSigned(p []byte) (sample [2]float64, n int) {
	return f.decode(true, p)
}

// DecodeUnsigned decodes a single sample encoded in f.Width() bytes from p in unsigned format.
func (f Format) DecodeUnsigned(p []byte) (sample [2]float64, n int) {
	return f.decode(false, p)
}

func (f Format) encode(signed bool, p []byte, sample [2]float64) (n int) {
	switch {
	case f.NumChannels == 1:
		x := norm((sample[0] + sample[1]) / 2)
		p = p[encodeFloat(signed, p, f.Precision, x):]
	case f.NumChannels >= 2:
		for c := range sample {
			x := norm(sample[c])
			p = p[encodeFloat(signed, p, f.Precision, x):]
		}
		for c := len(sample); c < f.NumChannels; c++ {
			p = p[encodeFloat(signed, p, f.Precision, 0):]
		}
	default:
		panic(fmt.Errorf("format: encode: invalid number of channels: %d", f.NumChannels))
	}
	return f.Width()
}

func (f Format) decode(signed bool, p []byte) (sample [2]float64, n int) {
	switch {
	case f.NumChannels == 1:
		x, _ := decodeFloat(signed, p, f.Precision)
		return [2]float64{x, x}, f.Width()
	case f.NumChannels >= 2:
		for c := range sample {
			x, n := decodeFloat(signed, p, f.Precision)
			sample[c] = x
			p = p[n:]
		}
		for c := len(sample); c < f.NumChannels; c++ {
			_, n := decodeFloat(signed, p, f.Precision)
			p = p[n:]
		}
		return sample, f.Width()
	default:
		panic(fmt.Errorf("format: decode: invalid number of channels: %d", f.NumChannels))
	}
}

func encodeFloat(signed bool, p []byte, precision int, x float64) (n int) {
	var xUint64 uint64
	if signed {
		xUint64 = floatToSigned(precision, x)
	} else {
		xUint64 = floatToUnsigned(precision, x)
	}
	for i := 0; i < precision; i++ {
		p[i] = byte(xUint64)
		xUint64 >>= 8
	}
	return precision
}

func decodeFloat(signed bool, p []byte, precision int) (x float64, n int) {
	var xUint64 uint64
	for i := precision - 1; i >= 0; i-- {
		xUint64 <<= 8
		xUint64 += uint64(p[i])
	}
	if signed {
		return signedToFloat(precision, xUint64), precision
	}
	return unsignedToFloat(precision, xUint64), precision
}

func floatToSigned(precision int, x float64) uint64 {
	if x < 0 {
		compl := uint64(-x * float64(uint64(1)<<uint(precision*8-1)-1))
		return uint64(1<<uint(precision*8)) - compl
	}
	return uint64(x * float64(uint64(1)<<uint(precision*8-1)-1))
}

func floatToUnsigned(precision int, x float64) uint64 {
	return uint64((x + 1) / 2 * float64(uint64(1)<<uint(precision*8)-1))
}

func signedToFloat(precision int, xUint64 uint64) float64 {
	if xUint64 >= 1<<uint(precision*8-1) {
		compl := 1<<uint(precision*8) - xUint64
		return -float64(int64(compl)) / float64(uint64(1)<<uint(precision*8-1)-1)
	}
	return float64(int64(xUint64)) / float64(uint64(1)<<uint(precision*8-1)-1)
}

func unsignedToFloat(precision int, xUint64 uint64) float64 {
	return float64(xUint64)/float64(uint(1)<<uint(precision*8)-1)*2 - 1
}

func norm(x float64) float64 {
	if x < -1 {
		return -1
	}
	if x > +1 {
		return +1
	}
	return x
}

type Buffer struct {
	f    Format
	data []byte
}

func NewBuffer(f Format) *Buffer {
	return &Buffer{f: f}
}

func (b *Buffer) Format() Format {
	return b.f
}

func (b *Buffer) Len() int {
	return len(b.data)
}

func (b *Buffer) Duration() time.Duration {
	return b.f.Duration(len(b.data) / b.f.Width())
}

func (b *Buffer) Append(s Streamer) {
	var (
		samples [512][2]float64
		p       = make([]byte, b.f.Width())
	)
	for {
		n, ok := s.Stream(samples[:])
		if !ok {
			break
		}
		for _, sample := range samples[:n] {
			b.f.EncodeSigned(p, sample)
			b.data = append(b.data, p...)
		}
	}
}

func (b *Buffer) Streamer(from, to time.Duration) StreamSeeker {
	fromByte := b.f.NumSamples(from) * b.f.Width()
	toByte := b.f.NumSamples(to) * b.f.Width()
	return &bufferStreamer{
		f:    b.f,
		data: b.data[fromByte:toByte],
		pos:  0,
	}
}

type bufferStreamer struct {
	f    Format
	data []byte
	pos  int
}

func (bs *bufferStreamer) Stream(samples [][2]float64) (n int, ok bool) {
	if bs.pos >= len(bs.data) {
		return 0, false
	}
	for i := range samples {
		if bs.pos >= len(bs.data) {
			break
		}
		sample, advance := bs.f.DecodeSigned(bs.data[bs.pos:])
		samples[i] = sample
		bs.pos += advance
		n++
	}
	return n, true
}

func (bs *bufferStreamer) Err() error {
	return nil
}

func (bs *bufferStreamer) Duration() time.Duration {
	return bs.f.Duration(len(bs.data) / bs.f.Width())
}

func (bs *bufferStreamer) Position() time.Duration {
	return bs.f.Duration(bs.pos / bs.f.Width())
}

func (bs *bufferStreamer) Seek(d time.Duration) error {
	if d < 0 || bs.Duration() < d {
		return fmt.Errorf("buffer: seek duration %v out of range [%v, %v]", d, 0, bs.Duration())
	}
	bs.pos = bs.f.NumSamples(d) * bs.f.Width()
	return nil
}
<commit_msg>fix format encode/decode<commit_after>package beep

import (
	"fmt"
	"math"
	"time"
)

// Format is the format of a Buffer or another audio source.
type Format struct {
	// SampleRate is the number of samples per second.
	SampleRate int

	// NumChannels is the number of channels. The value of 1 is mono, the value of 2 is stereo.
	// The samples should always be interleaved.
	NumChannels int

	// Precision is the number of bytes used to encode a single sample.
	Precision int
}

// Width returns the number of bytes per one sample (all channels).
//
// This is equal to f.NumChannels * f.Precision.
func (f Format) Width() int {
	return f.NumChannels * f.Precision
}

// Duration returns the duration of n samples in this format.
func (f Format) Duration(n int) time.Duration {
	return time.Second * time.Duration(n) / time.Duration(f.SampleRate)
}

// NumSamples returns the number of samples in this format which last for d duration.
func (f Format) NumSamples(d time.Duration) int {
	return int(d * time.Duration(f.SampleRate) / time.Second)
}

// EncodeSigned encodes a single sample in f.Width() bytes to p in signed format.
func (f Format) EncodeSigned(p []byte, sample [2]float64) (n int) {
	return f.encode(true, p, sample)
}

// EncodeUnsigned encodes a single sample in f.Width() bytes to p in unsigned format.
func (f Format) EncodeUnsigned(p []byte, sample [2]float64) (n int) {
	return f.encode(false, p, sample)
}

// DecodeSigned decodes a single sample encoded in f.Width() bytes from p in signed format.
func (f Format) DecodeSigned(p []byte) (sample [2]float64, n int) {
	return f.decode(true, p)
}

// DecodeUnsigned decodes a single sample encoded in f.Width() bytes from p in unsigned format.
func (f Format) DecodeUnsigned(p []byte) (sample [2]float64, n int) {
	return f.decode(false, p)
}

func (f Format) encode(signed bool, p []byte, sample [2]float64) (n int) {
	switch {
	case f.NumChannels == 1:
		x := norm((sample[0] + sample[1]) / 2)
		p = p[encodeFloat(signed, f.Precision, p, x):]
	case f.NumChannels >= 2:
		for c := range sample {
			x := norm(sample[c])
			p = p[encodeFloat(signed, f.Precision, p, x):]
		}
		for c := len(sample); c < f.NumChannels; c++ {
			p = p[encodeFloat(signed, f.Precision, p, 0):]
		}
	default:
		panic(fmt.Errorf("format: encode: invalid number of channels: %d", f.NumChannels))
	}
	return f.Width()
}

func (f Format) decode(signed bool, p []byte) (sample [2]float64, n int) {
	switch {
	case f.NumChannels == 1:
		x, _ := decodeFloat(signed, f.Precision, p)
		return [2]float64{x, x}, f.Width()
	case f.NumChannels >= 2:
		for c := range sample {
			x, n := decodeFloat(signed, f.Precision, p)
			sample[c] = x
			p = p[n:]
		}
		for c := len(sample); c < f.NumChannels; c++ {
			_, n := decodeFloat(signed, f.Precision, p)
			p = p[n:]
		}
		return sample, f.Width()
	default:
		panic(fmt.Errorf("format: decode: invalid number of channels: %d", f.NumChannels))
	}
}

func encodeFloat(signed bool, precision int, p []byte, x float64) (n int) {
	var xUint64 uint64
	if signed {
		xUint64 = floatToSigned(precision, x)
	} else {
		xUint64 = floatToUnsigned(precision, x)
	}
	for i := 0; i < precision; i++ {
		p[i] = byte(xUint64)
		xUint64 >>= 8
	}
	return precision
}

func decodeFloat(signed bool, precision int, p []byte) (x float64, n int) {
	var xUint64 uint64
	for i := precision - 1; i >= 0; i-- {
		xUint64 <<= 8
		xUint64 += uint64(p[i])
	}
	if signed {
		return signedToFloat(precision, xUint64), precision
	}
	return unsignedToFloat(precision, xUint64), precision
}

func floatToSigned(precision int, x float64) uint64 {
	if x < 0 {
		compl := uint64(-x * (math.Exp2(float64(precision)*8-1) - 1))
		return uint64(1<<uint(precision*8)) - compl
	}
	return uint64(x * (math.Exp2(float64(precision)*8-1) - 1))
}

func floatToUnsigned(precision int, x float64) uint64 {
	return uint64((x + 1) / 2 * (math.Exp2(float64(precision)*8) - 1))
}

func signedToFloat(precision int, xUint64 uint64) float64 {
	if xUint64 >= 1<<uint(precision*8-1) {
		compl := 1<<uint(precision*8) - xUint64
		return -float64(int64(compl)) / (math.Exp2(float64(precision)*8-1) - 1)
	}
	return float64(int64(xUint64)) / (math.Exp2(float64(precision)*8-1) - 1)
}

func unsignedToFloat(precision int, xUint64 uint64) float64 {
	return float64(xUint64)/(math.Exp2(float64(precision)*8)-1)*2 - 1
}

func norm(x float64) float64 {
	if x < -1 {
		return -1
	}
	if x > +1 {
		return +1
	}
	return x
}

type Buffer struct {
	f    Format
	data []byte
	tmp  []byte
}

func NewBuffer(f Format) *Buffer {
	return &Buffer{f: f, tmp: make([]byte, f.Width())}
}

func (b *Buffer) Format() Format {
	return b.f
}

func (b *Buffer) Duration() time.Duration {
	return b.f.Duration(len(b.data) / b.f.Width())
}

func (b *Buffer) Pop(d time.Duration) {
	if d > b.Duration() {
		d = b.Duration()
	}
	n := b.f.NumSamples(d)
	b.data = b.data[n:]
}

func (b *Buffer) Append(s Streamer) {
	var samples [512][2]float64
	for {
		n, ok := s.Stream(samples[:])
		if !ok {
			break
		}
		for _, sample := range samples[:n] {
			b.f.EncodeSigned(b.tmp, sample)
			b.data = append(b.data, b.tmp...)
		}
	}
}

func (b *Buffer) Streamer(from, to time.Duration) StreamSeeker {
	fromByte := b.f.NumSamples(from) * b.f.Width()
	toByte := b.f.NumSamples(to) * b.f.Width()
	return &bufferStreamer{
		f:    b.f,
		data: b.data[fromByte:toByte],
		pos:  0,
	}
}

type bufferStreamer struct {
	f    Format
	data []byte
	pos  int
}

func (bs *bufferStreamer) Stream(samples [][2]float64) (n int, ok bool) {
	if bs.pos >= len(bs.data) {
		return 0, false
	}
	for i := range samples {
		if bs.pos >= len(bs.data) {
			break
		}
		sample, advance := bs.f.DecodeSigned(bs.data[bs.pos:])
		samples[i] = sample
		bs.pos += advance
		n++
	}
	return n, true
}

func (bs *bufferStreamer) Err() error {
	return nil
}

func (bs *bufferStreamer) Duration() time.Duration {
	return bs.f.Duration(len(bs.data) / bs.f.Width())
}

func (bs *bufferStreamer) Position() time.Duration {
	return bs.f.Duration(bs.pos / bs.f.Width())
}

func (bs *bufferStreamer) Seek(d time.Duration) error {
	if d < 0 || bs.Duration() < d {
		return fmt.Errorf("buffer: seek duration %v out of range [%v, %v]", d, 0, bs.Duration())
	}
	bs.pos = bs.f.NumSamples(d) * bs.f.Width()
	return nil
}
<|endoftext|>


<commit_before>// package multibuf implements buffer optimized for streaming large chunks of data,
// multiple reads and  optional partial buffering to disk.
package multibuf

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

// MultiBuf provides Read, Close, Seek and Size methods. In addition to that it supports WriterTo interface
// to provide efficient writing schemes, as functions like io.Copy use WriterTo when it's available.
type MultiBuf interface {
	io.Reader
	io.Seeker
	io.Closer
	io.WriterTo

	// Size calculates and returns the total size of the reader and not the length remaining.
	Size() (int64, error)
}

// MaxBytes, ignored if set to value >=, if request exceeds the specified limit, the reader will return error,
// by default buffer is not limited
func MaxBytes(m int64) optionSetter {
	return func(o *options) error {
		if m <= 0 {
			return fmt.Errorf("MaxSizeBytes should be > 0")
		}
		o.maxSizeBytes = m
		return nil
	}
}

// MemBytes specifies the largest buffer to hold in RAM before writing to disk, default is 1MB
func MemBytes(m int64) optionSetter {
	return func(o *options) error {
		if m < 0 {
			return fmt.Errorf("MemBytes should be >= 0")
		}
		o.maxSizeBytes = m
		return nil
	}
}

// New returns MultiBuf that can limit the size of the buffer and persist large buffers to disk.
// By default New returns unbound buffer that will read up to 1MB in RAM and will start buffering to disk
// It supports multiple functional optional arguments:
//
//    // Buffer up to 1MB in RAM and limit max buffer size to 20MB
//    multibuf.New(r, multibuf.MemBytes(1024 * 1024), multibuf.MaxBytes(1024 * 1024 * 20))
//
//
func New(input io.Reader, setters ...optionSetter) (MultiBuf, error) {
	o := options{
		memBytes:     DefaultMemBytes,
		maxSizeBytes: DefaultMaxSizeBytes,
	}

	for _, s := range setters {
		if err := s(&o); err != nil {
			return nil, err
		}
	}

	memReader := &io.LimitedReader{
		R: input,      // Read from this reader
		N: o.memBytes, // Maximum amount of data to read
	}
	readers := make([]io.ReadSeeker, 0, 2)

	buffer, err := ioutil.ReadAll(memReader)
	if err != nil {
		return nil, err
	}
	readers = append(readers, bytes.NewReader(buffer))

	var file *os.File
	// This means that we have exceeded all the memory capacity and we will start buffering the body to disk.
	totalBytes := int64(len(buffer))
	if memReader.N <= 0 {
		file, err = ioutil.TempFile("", "multibuf-")
		if err != nil {
			return nil, err
		}
		os.Remove(file.Name())

		readSrc := input
		if o.maxSizeBytes > 0 {
			readSrc = &maxReader{R: input, Max: o.maxSizeBytes - o.memBytes}
		}

		writtenBytes, err := io.Copy(file, readSrc)
		if err != nil {
			return nil, err
		}
		totalBytes += writtenBytes
		file.Seek(0, 0)
		readers = append(readers, file)
	}

	var cleanupFn cleanupFunc
	if file != nil {
		cleanupFn = func() error {
			file.Close()
			return nil
		}
	}
	return newBuf(totalBytes, cleanupFn, readers...), nil
}

// MaxSizeReachedError is returned when the maximum allowed buffer size is reached when reading
type MaxSizeReachedError struct {
	MaxSize int64
}

func (e *MaxSizeReachedError) Error() string {
	return fmt.Sprintf("Maximum size %d was reached", e)
}

const (
	DefaultMemBytes     = 1048576
	DefaultMaxSizeBytes = -1
	// Equivalent of bytes.MinRead used in ioutil.ReadAll
	DefaultBufferBytes = 512
)

// Constraints:
//  - Implements io.Reader
//  - Implements Seek(0, 0)
//	- Designed for Write once, Read many times.
type multiReaderSeek struct {
	length  int64
	readers []io.ReadSeeker
	mr      io.Reader
	cleanup cleanupFunc
}

type cleanupFunc func() error

func newBuf(length int64, cleanup cleanupFunc, readers ...io.ReadSeeker) *multiReaderSeek {
	converted := make([]io.Reader, len(readers))
	for i, r := range readers {
		// This conversion is safe as ReadSeeker includes Reader
		converted[i] = r.(io.Reader)
	}

	return &multiReaderSeek{
		length:  length,
		readers: readers,
		mr:      io.MultiReader(converted...),
		cleanup: cleanup,
	}
}

func (mr *multiReaderSeek) Close() (err error) {
	if mr.cleanup != nil {
		return mr.cleanup()
	}
	return nil
}

func (mr *multiReaderSeek) WriteTo(w io.Writer) (int64, error) {
	b := make([]byte, DefaultBufferBytes)
	var total int64
	for {
		n, err := mr.mr.Read(b)
		// Recommended way is to always handle non 0 reads despite the errors
		if n > 0 {
			nw, errw := w.Write(b[:n])
			total += int64(nw)
			// Write must return a non-nil error if it returns nw < n
			if nw != n || errw != nil {
				return total, errw
			}
		}
		if err != nil {
			if err == io.EOF {
				return total, nil
			}
			return total, err
		}
	}
}

func (mr *multiReaderSeek) Read(p []byte) (n int, err error) {
	return mr.mr.Read(p)
}

func (mr *multiReaderSeek) Size() (int64, error) {
	return mr.length, nil
}

func (mr *multiReaderSeek) Seek(offset int64, whence int) (int64, error) {
	// TODO: implement other whence
	// TODO: implement real offsets

	if whence != 0 {
		return 0, fmt.Errorf("multiReaderSeek: unsupported whence")
	}

	if offset != 0 {
		return 0, fmt.Errorf("multiReaderSeek: unsupported offset")
	}

	for _, seeker := range mr.readers {
		seeker.Seek(0, 0)
	}

	ior := make([]io.Reader, len(mr.readers))
	for i, arg := range mr.readers {
		ior[i] = arg.(io.Reader)
	}
	mr.mr = io.MultiReader(ior...)

	return 0, nil
}

type options struct {
	// MemBufferBytes sets up the size of the memory buffer for this request.
	// If the data size exceeds the limit, the remaining request part will be saved on the file system.
	memBytes int64

	maxSizeBytes int64
}

type optionSetter func(o *options) error

// MaxReader does not allow to read more than Max bytes and returns error if this limit has been exceeded.
type maxReader struct {
	R   io.Reader // underlying reader
	N   int64     // bytes read
	Max int64     // max bytes to read
}

func (r *maxReader) Read(p []byte) (int, error) {
	readBytes, err := r.R.Read(p)
	if err != nil && err != io.EOF {
		return readBytes, err
	}

	r.N += int64(readBytes)
	if r.N > r.Max {
		return readBytes, &MaxSizeReachedError{MaxSize: r.Max}
	}
	return readBytes, err
}
<commit_msg>Fix behavior<commit_after>// package multibuf implements buffer optimized for streaming large chunks of data,
// multiple reads and  optional partial buffering to disk.
package multibuf

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

// MultiBuf provides Read, Close, Seek and Size methods. In addition to that it supports WriterTo interface
// to provide efficient writing schemes, as functions like io.Copy use WriterTo when it's available.
type MultiBuf interface {
	io.Reader
	io.Seeker
	io.Closer
	io.WriterTo

	// Size calculates and returns the total size of the reader and not the length remaining.
	Size() (int64, error)
}

// MaxBytes, ignored if set to value >=, if request exceeds the specified limit, the reader will return error,
// by default buffer is not limited, negative values mean no limit
func MaxBytes(m int64) optionSetter {
	return func(o *options) error {
		o.maxSizeBytes = m
		return nil
	}
}

// MemBytes specifies the largest buffer to hold in RAM before writing to disk, default is 1MB
func MemBytes(m int64) optionSetter {
	return func(o *options) error {
		if m < 0 {
			return fmt.Errorf("MemBytes should be >= 0")
		}
		o.maxSizeBytes = m
		return nil
	}
}

// New returns MultiBuf that can limit the size of the buffer and persist large buffers to disk.
// By default New returns unbound buffer that will read up to 1MB in RAM and will start buffering to disk
// It supports multiple functional optional arguments:
//
//    // Buffer up to 1MB in RAM and limit max buffer size to 20MB
//    multibuf.New(r, multibuf.MemBytes(1024 * 1024), multibuf.MaxBytes(1024 * 1024 * 20))
//
//
func New(input io.Reader, setters ...optionSetter) (MultiBuf, error) {
	o := options{
		memBytes:     DefaultMemBytes,
		maxSizeBytes: DefaultMaxSizeBytes,
	}

	for _, s := range setters {
		if err := s(&o); err != nil {
			return nil, err
		}
	}

	memReader := &io.LimitedReader{
		R: input,      // Read from this reader
		N: o.memBytes, // Maximum amount of data to read
	}
	readers := make([]io.ReadSeeker, 0, 2)

	buffer, err := ioutil.ReadAll(memReader)
	if err != nil {
		return nil, err
	}
	readers = append(readers, bytes.NewReader(buffer))

	var file *os.File
	// This means that we have exceeded all the memory capacity and we will start buffering the body to disk.
	totalBytes := int64(len(buffer))
	if memReader.N <= 0 {
		file, err = ioutil.TempFile("", "multibuf-")
		if err != nil {
			return nil, err
		}
		os.Remove(file.Name())

		readSrc := input
		if o.maxSizeBytes > 0 {
			readSrc = &maxReader{R: input, Max: o.maxSizeBytes - o.memBytes}
		}

		writtenBytes, err := io.Copy(file, readSrc)
		if err != nil {
			return nil, err
		}
		totalBytes += writtenBytes
		file.Seek(0, 0)
		readers = append(readers, file)
	}

	var cleanupFn cleanupFunc
	if file != nil {
		cleanupFn = func() error {
			file.Close()
			return nil
		}
	}
	return newBuf(totalBytes, cleanupFn, readers...), nil
}

// MaxSizeReachedError is returned when the maximum allowed buffer size is reached when reading
type MaxSizeReachedError struct {
	MaxSize int64
}

func (e *MaxSizeReachedError) Error() string {
	return fmt.Sprintf("Maximum size %d was reached", e)
}

const (
	DefaultMemBytes     = 1048576
	DefaultMaxSizeBytes = -1
	// Equivalent of bytes.MinRead used in ioutil.ReadAll
	DefaultBufferBytes = 512
)

// Constraints:
//  - Implements io.Reader
//  - Implements Seek(0, 0)
//	- Designed for Write once, Read many times.
type multiReaderSeek struct {
	length  int64
	readers []io.ReadSeeker
	mr      io.Reader
	cleanup cleanupFunc
}

type cleanupFunc func() error

func newBuf(length int64, cleanup cleanupFunc, readers ...io.ReadSeeker) *multiReaderSeek {
	converted := make([]io.Reader, len(readers))
	for i, r := range readers {
		// This conversion is safe as ReadSeeker includes Reader
		converted[i] = r.(io.Reader)
	}

	return &multiReaderSeek{
		length:  length,
		readers: readers,
		mr:      io.MultiReader(converted...),
		cleanup: cleanup,
	}
}

func (mr *multiReaderSeek) Close() (err error) {
	if mr.cleanup != nil {
		return mr.cleanup()
	}
	return nil
}

func (mr *multiReaderSeek) WriteTo(w io.Writer) (int64, error) {
	b := make([]byte, DefaultBufferBytes)
	var total int64
	for {
		n, err := mr.mr.Read(b)
		// Recommended way is to always handle non 0 reads despite the errors
		if n > 0 {
			nw, errw := w.Write(b[:n])
			total += int64(nw)
			// Write must return a non-nil error if it returns nw < n
			if nw != n || errw != nil {
				return total, errw
			}
		}
		if err != nil {
			if err == io.EOF {
				return total, nil
			}
			return total, err
		}
	}
}

func (mr *multiReaderSeek) Read(p []byte) (n int, err error) {
	return mr.mr.Read(p)
}

func (mr *multiReaderSeek) Size() (int64, error) {
	return mr.length, nil
}

func (mr *multiReaderSeek) Seek(offset int64, whence int) (int64, error) {
	// TODO: implement other whence
	// TODO: implement real offsets

	if whence != 0 {
		return 0, fmt.Errorf("multiReaderSeek: unsupported whence")
	}

	if offset != 0 {
		return 0, fmt.Errorf("multiReaderSeek: unsupported offset")
	}

	for _, seeker := range mr.readers {
		seeker.Seek(0, 0)
	}

	ior := make([]io.Reader, len(mr.readers))
	for i, arg := range mr.readers {
		ior[i] = arg.(io.Reader)
	}
	mr.mr = io.MultiReader(ior...)

	return 0, nil
}

type options struct {
	// MemBufferBytes sets up the size of the memory buffer for this request.
	// If the data size exceeds the limit, the remaining request part will be saved on the file system.
	memBytes int64

	maxSizeBytes int64
}

type optionSetter func(o *options) error

// MaxReader does not allow to read more than Max bytes and returns error if this limit has been exceeded.
type maxReader struct {
	R   io.Reader // underlying reader
	N   int64     // bytes read
	Max int64     // max bytes to read
}

func (r *maxReader) Read(p []byte) (int, error) {
	readBytes, err := r.R.Read(p)
	if err != nil && err != io.EOF {
		return readBytes, err
	}

	r.N += int64(readBytes)
	if r.N > r.Max {
		return readBytes, &MaxSizeReachedError{MaxSize: r.Max}
	}
	return readBytes, err
}
<|endoftext|>


<commit_before>package buffer

import (
	"io"
)

const (
	maxUint   = ^uint32(0)
	maxInt    = int32(maxUint >> 1)
	maxUint64 = ^uint64(0)
	maxInt64  = int64(maxUint64 >> 1)
	maxAlloc  = int64(1024 * 32)
)

type Buffer interface {
	Len() int64
	Cap() int64
	io.Reader
	io.Writer
}

type buffer struct {
	head []byte
	Buffer
}

func MaxCap() int64 {
	return maxInt64
}

func LimitAlloc(n int64) int64 {
	if n > maxAlloc {
		return maxAlloc
	}
	return n
}

func Gap(buf Buffer) int64 {
	return buf.Cap() - buf.Len()
}

func Full(buf Buffer) bool {
	return Gap(buf) == 0
}

type Lener interface {
	Len() int64
}

func Empty(l Lener) bool {
	return l.Len() == 0
}

func RoomFor(buf Buffer, p []byte) bool {
	return Gap(buf) >= int64(len(p))
}

func ShrinkToRead(buf Buffer, p []byte) []byte {
	if buf.Len() < int64(len(p)) {
		return p[:buf.Len()]
	}
	return p
}

func ShrinkToFit(buf Buffer, p []byte) []byte {
	if !RoomFor(buf, p) {
		p = p[:Gap(buf)]
	}
	return p
}

func TotalLen(buffers []Buffer) (n int64) {
	for _, buffer := range buffers {
		if n > MaxCap()-buffer.Len() {
			return MaxCap()
		} else {
			n += buffer.Len()
		}
	}
	return n
}

func TotalCap(buffers []Buffer) (n int64) {
	for _, buffer := range buffers {
		if n > MaxCap()-buffer.Cap() {
			return MaxCap()
		} else {
			n += buffer.Cap()
		}
	}
	return n
}

func NewUnboundedBuffer(mem, chunk int64) Buffer {
	return NewMulti(New(mem), NewPartition(chunk, NewFile))
}
<commit_msg>Made buffer functions more generic<commit_after>package buffer

import (
	"io"
)

const (
	maxUint   = ^uint32(0)
	maxInt    = int32(maxUint >> 1)
	maxUint64 = ^uint64(0)
	maxInt64  = int64(maxUint64 >> 1)
	maxAlloc  = int64(1024 * 32)
)

type Lener interface {
	Len() int64
}

type Caper interface {
	Cap() int64
}

type LenCaper interface {
	Lener
	Caper
}

type Buffer interface {
	Lener
	Caper
	io.Reader
	io.Writer
}

type buffer struct {
	head []byte
	Buffer
}

func MaxCap() int64 {
	return maxInt64
}

func LimitAlloc(n int64) int64 {
	if n > maxAlloc {
		return maxAlloc
	}
	return n
}

func Gap(buf LenCaper) int64 {
	return buf.Cap() - buf.Len()
}

func Full(buf LenCaper) bool {
	return Gap(buf) == 0
}

func Empty(l Lener) bool {
	return l.Len() == 0
}

func RoomFor(buf LenCaper, p []byte) bool {
	return Gap(buf) >= int64(len(p))
}

func ShrinkToRead(buf Lener, p []byte) []byte {
	if buf.Len() < int64(len(p)) {
		return p[:buf.Len()]
	}
	return p
}

func ShrinkToFit(buf LenCaper, p []byte) []byte {
	if !RoomFor(buf, p) {
		p = p[:Gap(buf)]
	}
	return p
}

func TotalLen(buffers []Buffer) (n int64) {
	for _, buffer := range buffers {
		if n > MaxCap()-buffer.Len() {
			return MaxCap()
		} else {
			n += buffer.Len()
		}
	}
	return n
}

func TotalCap(buffers []Buffer) (n int64) {
	for _, buffer := range buffers {
		if n > MaxCap()-buffer.Cap() {
			return MaxCap()
		} else {
			n += buffer.Cap()
		}
	}
	return n
}

func NewUnboundedBuffer(mem, chunk int64) Buffer {
	return NewMulti(New(mem), NewPartition(chunk, NewFile))
}
<|endoftext|>


<commit_before>package kinesis

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"text/template"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/kinesis"
	"github.com/gliderlabs/logspout/router"
)

// PutRecordsLimit is the maximum number of records allowed for a PutRecords request.
var PutRecordsLimit = 500

// RecordSizeLimit is the maximum allowed size per record.
var RecordSizeLimit int = 1 * 1024 * 1024 // 1MB

// PutRecordsSizeLimit is the maximum allowed size per PutRecords request.
var PutRecordsSizeLimit int = 5 * 1024 * 1024 // 5MB

type recordBuffer struct {
	client   *kinesis.Kinesis
	pKeyTmpl *template.Template
	input    *kinesis.PutRecordsInput
	count    int
	byteSize int
}

func newRecordBuffer(client *kinesis.Kinesis, streamName string) (*recordBuffer, error) {
	pKeyTmpl, err := pKeyTmpl()
	if err != nil {
		return nil, err
	}

	input := &kinesis.PutRecordsInput{
		StreamName: aws.String(streamName),
		Records:    make([]*kinesis.PutRecordsRequestEntry, 0),
	}

	return &recordBuffer{
		client:   client,
		pKeyTmpl: pKeyTmpl,
		input:    input,
	}, nil
}

func pKeyTmpl() (*template.Template, error) {
	pKeyTmplString := os.Getenv("KINESIS_PARTITION_KEY_TEMPLATE")
	if pKeyTmplString == "" {
		return nil, errors.New("The partition key template is missing. Please set the KINESIS_PARTITION_KEY_TEMPLATE env variable")
	}

	pKeyTmpl, err := template.New("kinesisPartitionKey").Parse(pKeyTmplString)
	if err != nil {
		return nil, err
	}

	return pKeyTmpl, nil
}

func (r *recordBuffer) Add(m *router.Message) error {
	data := m.Data
	dataLen := len(data)

	// This record is too large, we can't submit it to kinesis.
	if dataLen > RecordSizeLimit {
		return errors.New(fmt.Sprintf("recordBuffer.Add: log data byte size (%d) is over the limit.", dataLen))
	}

	// Adding this event would make our request have too many records. Flush first.
	if r.count+1 > PutRecordsLimit {
		err := r.Flush()
		if err != nil {
			return err
		}
	}

	// Adding this event would make our request too large. Flush first.
	if r.byteSize+dataLen > PutRecordsSizeLimit {
		err := r.Flush()
		if err != nil {
			return err
		}
	}

	// Partition key
	pKey, err := pKey(r.pKeyTmpl, m)
	if err != nil {
		return err
	}

	// Add to count
	r.count += 1

	// Add data and partition key size to byteSize
	r.byteSize += dataLen + len(pKey)

	// Add record
	r.input.Records = append(r.input.Records, &kinesis.PutRecordsRequestEntry{
		Data:         []byte(data),
		PartitionKey: aws.String(pKey),
	})

	return nil
}

func (r *recordBuffer) Flush() error {
	if r.count == 0 {
		return nil
	}

	defer r.reset()

	_, err := r.client.PutRecords(r.input)
	if err != nil {
		return err
	}

	return nil
}

func (r *recordBuffer) reset() {
	r.count = 0
	r.byteSize = 0
	r.input.Records = make([]*kinesis.PutRecordsRequestEntry, 0)
}

func pKey(tmpl *template.Template, m *router.Message) (string, error) {
	var pKey bytes.Buffer
	err := tmpl.Execute(&pKey, m)
	if err != nil {
		return "", err
	}

	return pKey.String(), nil
}
<commit_msg>Add a mutex to prevent race condition bt Flush() and reset().<commit_after>package kinesis

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"sync"
	"text/template"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/kinesis"
	"github.com/gliderlabs/logspout/router"
)

// PutRecordsLimit is the maximum number of records allowed for a PutRecords request.
var PutRecordsLimit = 500

// RecordSizeLimit is the maximum allowed size per record.
var RecordSizeLimit int = 1 * 1024 * 1024 // 1MB

// PutRecordsSizeLimit is the maximum allowed size per PutRecords request.
var PutRecordsSizeLimit int = 5 * 1024 * 1024 // 5MB

// Prevent Flush() and reset() race condition.
var mutex sync.Mutex

type recordBuffer struct {
	client   *kinesis.Kinesis
	pKeyTmpl *template.Template
	input    *kinesis.PutRecordsInput
	count    int
	byteSize int
}

func newRecordBuffer(client *kinesis.Kinesis, streamName string) (*recordBuffer, error) {
	pKeyTmpl, err := pKeyTmpl()
	if err != nil {
		return nil, err
	}

	input := &kinesis.PutRecordsInput{
		StreamName: aws.String(streamName),
		Records:    make([]*kinesis.PutRecordsRequestEntry, 0),
	}

	return &recordBuffer{
		client:   client,
		pKeyTmpl: pKeyTmpl,
		input:    input,
	}, nil
}

func pKeyTmpl() (*template.Template, error) {
	pKeyTmplString := os.Getenv("KINESIS_PARTITION_KEY_TEMPLATE")
	if pKeyTmplString == "" {
		return nil, errors.New("The partition key template is missing. Please set the KINESIS_PARTITION_KEY_TEMPLATE env variable")
	}

	pKeyTmpl, err := template.New("kinesisPartitionKey").Parse(pKeyTmplString)
	if err != nil {
		return nil, err
	}

	return pKeyTmpl, nil
}

func (r *recordBuffer) Add(m *router.Message) error {
	data := m.Data
	dataLen := len(data)

	// This record is too large, we can't submit it to kinesis.
	if dataLen > RecordSizeLimit {
		return errors.New(fmt.Sprintf("recordBuffer.Add: log data byte size (%d) is over the limit.", dataLen))
	}

	// Adding this event would make our request have too many records. Flush first.
	if r.count+1 > PutRecordsLimit {
		err := r.Flush()
		if err != nil {
			return err
		}
	}

	// Adding this event would make our request too large. Flush first.
	if r.byteSize+dataLen > PutRecordsSizeLimit {
		err := r.Flush()
		if err != nil {
			return err
		}
	}

	// Partition key
	pKey, err := pKey(r.pKeyTmpl, m)
	if err != nil {
		return err
	}

	// Add to count
	r.count += 1

	// Add data and partition key size to byteSize
	r.byteSize += dataLen + len(pKey)

	// Add record
	r.input.Records = append(r.input.Records, &kinesis.PutRecordsRequestEntry{
		Data:         []byte(data),
		PartitionKey: aws.String(pKey),
	})

	return nil
}

func (r *recordBuffer) Flush() error {
	mutex.Lock()
	defer mutex.Unlock()

	if r.count == 0 {
		return nil
	}

	defer r.reset()

	_, err := r.client.PutRecords(r.input)
	if err != nil {
		return err
	}

	return nil
}

func (r *recordBuffer) reset() {
	mutex.Lock()
	defer mutex.Unlock()

	r.count = 0
	r.byteSize = 0
	r.input.Records = make([]*kinesis.PutRecordsRequestEntry, 0)
}

func pKey(tmpl *template.Template, m *router.Message) (string, error) {
	var pKey bytes.Buffer
	err := tmpl.Execute(&pKey, m)
	if err != nil {
		return "", err
	}

	return pKey.String(), nil
}
<|endoftext|>


<commit_before>package std

import "github.com/DeedleFake/wdte"

func save(f wdte.Func, saved ...wdte.Func) wdte.Func {
	return wdte.GoFunc(func(frame []wdte.Func, args ...wdte.Func) wdte.Func {
		return f(frame, append(saved, args...))
	})
}

// Add returns the sum of its arguments. If called with only 1
// argument, it returns a function which adds arguments given to that
// one argument.
func Add(frame []wdte.Func, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return Add

	case 1:
		return save(Add, args[0])
	}

	var sum wdte.Number
	for _, arg := range args {
		sum += arg.Call(frame).(wdte.Number)
	}
	return sum
}

// Sub returns args[0] - args[1]. If called with only 1 argument, it
// returns a function which returns that argument minus the argument
// given.
func Sub(frame []wdte.Func, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return Sub

	case 1:
		return save(Sub, args[0])
	}

	a1 := args[0].Call(frame).(wdte.Number)
	a2 := args[1].Call(frame).(wdte.Number)
	return a1 - a2
}

// Mult returns the product of its arguments. If called with only 1
// argument, it returns a function that multiplies that argument by
// its own arguments.
func Mult(frame []wdte.Func, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return Mult

	case 1:
		return save(Mult, args[0])
	}

	p := wdte.Number(1)
	for _, arg := range args {
		p *= arg.Call(frame).(wdte.Number)
	}
	return p
}

// Div returns args[0] / args[1]. If called with only 1 argument, it
// returns a function which divides its own argument by the original
// argument.
func Div(frame []wdte.Func, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return Div

	case 1:
		return save(Div, args[0])
	}

	a1 := args[0].Call(frame).(wdte.Number)
	a2 := args[1].Call(frame).(wdte.Number)
	return a1 / a2
}

// Insert adds the functions in this package to m. It maps them to the
// cooresponding mathematical operators. For example, Add() becomes
// `+`, Sub() becomes `-`, and so on.
func Insert(m *wdte.Module) {
	m.Funcs["+"] = wdte.GoFunc(Add)
	m.Funcs["-"] = wdte.GoFunc(Sub)
	m.Funcs["*"] = wdte.GoFunc(Mult)
	m.Funcs["/"] = wdte.GoFunc(Div)
}
<commit_msg>std: Woops. Fix compilation errors.<commit_after>package std

import (
	"github.com/DeedleFake/wdte"
)

func save(f wdte.Func, saved ...wdte.Func) wdte.Func {
	return wdte.GoFunc(func(frame []wdte.Func, args ...wdte.Func) wdte.Func {
		return f.Call(frame, append(saved, args...)...)
	})
}

// Add returns the sum of its arguments. If called with only 1
// argument, it returns a function which adds arguments given to that
// one argument.
func Add(frame []wdte.Func, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return wdte.GoFunc(Add)

	case 1:
		return save(wdte.GoFunc(Add), args[0])
	}

	var sum wdte.Number
	for _, arg := range args {
		sum += arg.Call(frame).(wdte.Number)
	}
	return sum
}

// Sub returns args[0] - args[1]. If called with only 1 argument, it
// returns a function which returns that argument minus the argument
// given.
func Sub(frame []wdte.Func, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return wdte.GoFunc(Sub)

	case 1:
		return save(wdte.GoFunc(Sub), args[0])
	}

	a1 := args[0].Call(frame).(wdte.Number)
	a2 := args[1].Call(frame).(wdte.Number)
	return a1 - a2
}

// Mult returns the product of its arguments. If called with only 1
// argument, it returns a function that multiplies that argument by
// its own arguments.
func Mult(frame []wdte.Func, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return wdte.GoFunc(Mult)

	case 1:
		return save(wdte.GoFunc(Mult), args[0])
	}

	p := wdte.Number(1)
	for _, arg := range args {
		p *= arg.Call(frame).(wdte.Number)
	}
	return p
}

// Div returns args[0] / args[1]. If called with only 1 argument, it
// returns a function which divides its own argument by the original
// argument.
func Div(frame []wdte.Func, args ...wdte.Func) wdte.Func {
	switch len(args) {
	case 0:
		return wdte.GoFunc(Div)

	case 1:
		return save(wdte.GoFunc(Div), args[0])
	}

	a1 := args[0].Call(frame).(wdte.Number)
	a2 := args[1].Call(frame).(wdte.Number)
	return a1 / a2
}

// Insert adds the functions in this package to m. It maps them to the
// cooresponding mathematical operators. For example, Add() becomes
// `+`, Sub() becomes `-`, and so on.
func Insert(m *wdte.Module) {
	m.Funcs["+"] = wdte.GoFunc(Add)
	m.Funcs["-"] = wdte.GoFunc(Sub)
	m.Funcs["*"] = wdte.GoFunc(Mult)
	m.Funcs["/"] = wdte.GoFunc(Div)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/codegangsta/cli"
	"os"
	"log"
)

func main() {
	app := cli.NewApp()
	app.Name = "structr"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name: "config",
			Value: "",
			Usage: "configuration for structr",
		},
		cli.StringFlag{
			Name: "outDir",
			Value: "",
			Usage: "output directory for generated structure",
		},
	}
	app.Action = func(c *cli.Context) {
		args := c.Args()
		if len(args) < 1 {
			cli.ShowAppHelp(c)
			os.Exit(1)
		}
		context, err := NewContext(c.String("config"), c.String("outDir"), args)
		if err != nil {
			log.Fatalln("initialize error: ", err.Error())
		}
		bundler := NewJsonSchemaBundler(NewJsonSchemaLoader())
		if err := bundler.AddJsonSchema(context.Inputs...); err != nil {
			log.Fatalln("cannot add load json schema: ", err.Error())
		}
		creator := NewJsonSchemaNodeCreator(context, bundler)
		exporter := NewExporter(context)
		for _, b := range bundler.GetBundles() {
			structure, err := creator.CreateStructureNode(b)
			if err != nil {
				log.Fatalln("cannot create structure node: ", err.Error())
			}
			if err := exporter.Export(structure); err != nil {
				log.Fatalln("cannot export structure node: ", err.Error())
			}
		}
	}
	app.Run(os.Args)
}
<commit_msg>remove main action<commit_after>package main

import (
	"github.com/codegangsta/cli"
	"os"
)

var Version string

func main() {
	app := cli.NewApp()
	app.Name = "structr"
	app.Usage = "Generate structure definition(s) from JSON Schema"
	app.UsageText = "structr [command] [command options] [filepath...]"
	app.Author = "dameleon"
	app.Email = "dameleon@gmail.com"
	app.Version = Version
	app.Commands = Commands
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package couchdb

import (
	"fmt"
)

// http://docs.couchdb.org/en/latest/intro/api.html#server
type Server struct {
	Couchdb string
	Uuid    string
	Vendor  struct {
		Version string
		Name    string
	}
	Version string
}

// http://docs.couchdb.org/en/latest/api/database/common.html#get--db
type DatabaseInfo struct {
	DbName             string `json:"db_name"`
	DocCount           int    `json:"doc_count"`
	DocDelCount        int    `json:"doc_del_count"`
	UpdateSeq          int    `json:"update_seq"`
	PurgeSeq           int    `json:"purge_seq"`
	CompactRunning     bool   `json:"compact_running"`
	DiskSize           int    `json:"disk_size"`
	DataSize           int    `json:"data_size"`
	InstanceStartTime  string `json:"instance_start_time"`
	DiskFormatVersion  int    `json:"disk_format_version"`
	CommittedUpdateSeq int    `json:"committed_update_seq"`
}

type DatabaseResponse struct {
	Ok bool
}

type Error struct {
	Method     string
	Url        string
	StatusCode int
	Type       string `json:"error"`
	Reason     string
}

func (e *Error) Error() string {
	return fmt.Sprintf("CouchDB - %s %s, Status Code: %d, Error: %s, Reason: %s", e.Method, e.Url, e.StatusCode, e.Type, e.Reason)
}

type Document struct {
	Id          string                `json:"_id,omitempty"`
	Rev         string                `json:"_rev,omitempty"`
	Attachments map[string]Attachment `json:"_attachments,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/document/common.html#creating-multiple-attachments
type Attachment struct {
	Follows     bool   `json:"follows"`
	ContentType string `json:"content_type"`
	Length      int64  `json:"length"`
}

type CouchDoc interface {
	GetDocument() *Document
}

type DocumentResponse struct {
	Ok  bool
	Id  string
	Rev string
}

// http://docs.couchdb.org/en/latest/api/server/common.html#active-tasks
type Task struct {
	ChangesDone  int `json:"changes_done"`
	Database     string
	Pid          string
	Progress     int
	StartedOn    int `json:"started_on"`
	Status       string
	Task         string
	TotalChanges int `json:"total_changes"`
	Type         string
	UpdatedOn    string `json:"updated_on"`
}

type QueryParameters struct {
	Conflicts       bool          `url:"conflicts,omitempty"`
	Descending      bool          `url:"descending,omitempty"`
	EndKey          []interface{} `url:"endkey,comma,omitempty"`
	EndKeyDocId     string        `url:"end_key_doc_id,omitempty"`
	Group           bool          `url:"group,omitempty"`
	GroupLevel      int           `url:"group_level,omitempty"`
	IncludeDocs     bool          `url:"include_docs,omitempty"`
	Attachments     bool          `url:"attachments,omitempty"`
	AttEncodingInfo bool          `url:"att_encoding_info,omitempty"`
	InclusiveEnd    bool          `url:"inclusive_end,omitempty"`
	Key             string        `url:"key,omitempty"`
	Limit           int           `url:"limit,omitempty"`
	Reduce          bool          `url:"reduce,omitempty"`
	Skip            int           `url:"skip,omitempty"`
	Stale           string        `url:"stale,omitempty"`
	StartKey        []interface{} `url:"startkey,comma,omitempty"`
	StartKeyDocId   string        `url:"startkey_docid,omitempty"`
	UpdateSeq       bool          `url:"update_seq,omitempty"`
}

type ViewResponse struct {
	Offset    int   `json:"offset,omitempty"`
	Rows      []Row `json:"rows,omitempty"`
	TotalRows int   `json:"total_rows,omitempty"`
	UpdateSeq int   `json:"update_seq,omitempty"`
}

type Row struct {
	Id    string                 `json:"id"`
	Key   interface{}            `json:"key"`
	Value interface{}            `json:"value,omitempty"`
	Doc   map[string]interface{} `json:"doc,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_bulk_docs
type BulkDoc struct {
	AllOrNothing bool          `json:"all_or_nothing,omitempty"`
	Docs         []interface{} `json:"docs"`
	NewEdits     bool          `json:"new_edits,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/server/authn.html#cookie-authentication
type Credentials struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

type PostSessionResponse struct {
	Ok    bool
	Name  string
	Roles []string
}

type User struct {
	Document
	DerivedKey     string   `json:"derived_key,omitempty"`
	Name           string   `json:"name,omitempty"`
	Roles          []string `json:"roles"`
	Password       string   `json:"password,omitempty"`     // plain text password when creating the user
	PasswordSha    string   `json:"password_sha,omitempty"` // hashed password when requesting user information
	PasswordScheme string   `json:"password_scheme,omitempty"`
	Salt           string   `json:"salt,omitempty"`
	Type           string   `json:"type,omitempty"`
	Iterations     int      `json:"iterations,omitempty"`
}

func (user User) GetDocument() *Document {
	return &user.Document
}

func NewUser(name, password string, roles []string) User {
	user := User{
		Document: Document{
			Id: "org.couchdb.user:" + name,
		},
		DerivedKey:     "",
		Name:           name,
		Roles:          roles,
		Password:       password,
		PasswordSha:    "",
		PasswordScheme: "",
		Salt:           "",
		Type:           "user",
	}
	return user
}

type GetSessionResponse struct {
	Info struct {
		Authenticated          string   `json:"authenticated"`
		AuthenticationDb       string   `json:"authentication_db"`
		AuthenticationHandlers []string `json:"authentication_handlers"`
	} `json:"info"`
	Ok          bool `json:"ok"`
	UserContext struct {
		Db    string   `json:"db"`
		Name  string   `json:"name"`
		Roles []string `json:"roles"`
	} `json:"userCtx"`
}
<commit_msg>make startkey and endkey string type<commit_after>package couchdb

import (
	"fmt"
)

// http://docs.couchdb.org/en/latest/intro/api.html#server
type Server struct {
	Couchdb string
	Uuid    string
	Vendor  struct {
		Version string
		Name    string
	}
	Version string
}

// http://docs.couchdb.org/en/latest/api/database/common.html#get--db
type DatabaseInfo struct {
	DbName             string `json:"db_name"`
	DocCount           int    `json:"doc_count"`
	DocDelCount        int    `json:"doc_del_count"`
	UpdateSeq          int    `json:"update_seq"`
	PurgeSeq           int    `json:"purge_seq"`
	CompactRunning     bool   `json:"compact_running"`
	DiskSize           int    `json:"disk_size"`
	DataSize           int    `json:"data_size"`
	InstanceStartTime  string `json:"instance_start_time"`
	DiskFormatVersion  int    `json:"disk_format_version"`
	CommittedUpdateSeq int    `json:"committed_update_seq"`
}

type DatabaseResponse struct {
	Ok bool
}

type Error struct {
	Method     string
	Url        string
	StatusCode int
	Type       string `json:"error"`
	Reason     string
}

func (e *Error) Error() string {
	return fmt.Sprintf("CouchDB - %s %s, Status Code: %d, Error: %s, Reason: %s", e.Method, e.Url, e.StatusCode, e.Type, e.Reason)
}

type Document struct {
	Id          string                `json:"_id,omitempty"`
	Rev         string                `json:"_rev,omitempty"`
	Attachments map[string]Attachment `json:"_attachments,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/document/common.html#creating-multiple-attachments
type Attachment struct {
	Follows     bool   `json:"follows"`
	ContentType string `json:"content_type"`
	Length      int64  `json:"length"`
}

type CouchDoc interface {
	GetDocument() *Document
}

type DocumentResponse struct {
	Ok  bool
	Id  string
	Rev string
}

// http://docs.couchdb.org/en/latest/api/server/common.html#active-tasks
type Task struct {
	ChangesDone  int `json:"changes_done"`
	Database     string
	Pid          string
	Progress     int
	StartedOn    int `json:"started_on"`
	Status       string
	Task         string
	TotalChanges int `json:"total_changes"`
	Type         string
	UpdatedOn    string `json:"updated_on"`
}

type QueryParameters struct {
	Conflicts       bool   `url:"conflicts,omitempty"`
	Descending      bool   `url:"descending,omitempty"`
	EndKey          string `url:"endkey,comma,omitempty"`
	EndKeyDocId     string `url:"end_key_doc_id,omitempty"`
	Group           bool   `url:"group,omitempty"`
	GroupLevel      int    `url:"group_level,omitempty"`
	IncludeDocs     bool   `url:"include_docs,omitempty"`
	Attachments     bool   `url:"attachments,omitempty"`
	AttEncodingInfo bool   `url:"att_encoding_info,omitempty"`
	InclusiveEnd    bool   `url:"inclusive_end,omitempty"`
	Key             string `url:"key,omitempty"`
	Limit           int    `url:"limit,omitempty"`
	Reduce          bool   `url:"reduce,omitempty"`
	Skip            int    `url:"skip,omitempty"`
	Stale           string `url:"stale,omitempty"`
	StartKey        string `url:"startkey,comma,omitempty"`
	StartKeyDocId   string `url:"startkey_docid,omitempty"`
	UpdateSeq       bool   `url:"update_seq,omitempty"`
}

type ViewResponse struct {
	Offset    int   `json:"offset,omitempty"`
	Rows      []Row `json:"rows,omitempty"`
	TotalRows int   `json:"total_rows,omitempty"`
	UpdateSeq int   `json:"update_seq,omitempty"`
}

type Row struct {
	Id    string                 `json:"id"`
	Key   interface{}            `json:"key"`
	Value interface{}            `json:"value,omitempty"`
	Doc   map[string]interface{} `json:"doc,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_bulk_docs
type BulkDoc struct {
	AllOrNothing bool          `json:"all_or_nothing,omitempty"`
	Docs         []interface{} `json:"docs"`
	NewEdits     bool          `json:"new_edits,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/server/authn.html#cookie-authentication
type Credentials struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

type PostSessionResponse struct {
	Ok    bool
	Name  string
	Roles []string
}

type User struct {
	Document
	DerivedKey     string   `json:"derived_key,omitempty"`
	Name           string   `json:"name,omitempty"`
	Roles          []string `json:"roles"`
	Password       string   `json:"password,omitempty"`     // plain text password when creating the user
	PasswordSha    string   `json:"password_sha,omitempty"` // hashed password when requesting user information
	PasswordScheme string   `json:"password_scheme,omitempty"`
	Salt           string   `json:"salt,omitempty"`
	Type           string   `json:"type,omitempty"`
	Iterations     int      `json:"iterations,omitempty"`
}

func (user User) GetDocument() *Document {
	return &user.Document
}

func NewUser(name, password string, roles []string) User {
	user := User{
		Document: Document{
			Id: "org.couchdb.user:" + name,
		},
		DerivedKey:     "",
		Name:           name,
		Roles:          roles,
		Password:       password,
		PasswordSha:    "",
		PasswordScheme: "",
		Salt:           "",
		Type:           "user",
	}
	return user
}

type GetSessionResponse struct {
	Info struct {
		Authenticated          string   `json:"authenticated"`
		AuthenticationDb       string   `json:"authentication_db"`
		AuthenticationHandlers []string `json:"authentication_handlers"`
	} `json:"info"`
	Ok          bool `json:"ok"`
	UserContext struct {
		Db    string   `json:"db"`
		Name  string   `json:"name"`
		Roles []string `json:"roles"`
	} `json:"userCtx"`
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/julienschmidt/httprouter"
	//"net/http"
	//"net/http/httptest"
	//"github.com/Charlesworth/phoneBook"
	"reflect"
	"runtime"
	"testing"
)

//func main() {}

func TestNewRouter(t *testing.T) {
	//Get NewRouter to return *httpRouter
	router := NewRouter()

	//Did it return anything?
	if router == nil {
		t.Error("Router() did not return anything *httprouter.Router")
	}

	//did it return a *httpRouter?
	if reflect.TypeOf(router) != reflect.TypeOf(httprouter.New()) {
		t.Error("Router() did not return type *httprouter")
	}

}

func TestSetProc(t *testing.T) {
	SetProc()

	if runtime.GOMAXPROCS(0) != 2 {
		t.Error("Application not using 2 processors as set by setProc()")
	}
}

func Testmain(t *testing.T) {

}

func TestNewBoltClient(t *testing.T) {
	NewBoltClient()

}
<commit_msg>updated NewBoltClient tests<commit_after>package main

import (
	"github.com/julienschmidt/httprouter"
	//"net/http"
	//"net/http/httptest"
	//"github.com/Charlesworth/phoneBook"
	//"fmt"
	"github.com/boltdb/bolt"
	"reflect"
	"runtime"
	"testing"
)

//func main() {}

func TestNewRouter(t *testing.T) {
	//Get NewRouter to return *httpRouter
	router := NewRouter()

	//Did it return anything?
	if router == nil {
		t.Error("Router() did not return anything *httprouter.Router")
	}

	//did it return a *httpRouter?
	if reflect.TypeOf(router) != reflect.TypeOf(httprouter.New()) {
		t.Error("Router() did not return type *httprouter")
	}

}

func TestSetProc(t *testing.T) {
	SetProc()

	if runtime.GOMAXPROCS(0) != 2 {
		t.Error("Application not using 2 processors as set by setProc()")
	}
}

func Testmain(t *testing.T) {

}

func TestNewBoltClient(t *testing.T) {
	boltTest := NewBoltClient()

	boltTest.Mutex.Lock()

	//Test creating bucket
	err := boltTest.DB.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists([]byte("test"))

		return err
	})
	if err != nil {
		t.Error(err)
	}

	//Write to bucket
	err = boltTest.DB.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("test"))
		err = b.Put([]byte("hello"), []byte("world"))
		return err
	})
	if err != nil {
		t.Error(err)
	}

	boltTest.Mutex.Unlock()
	boltTest.Mutex.RLock()

	//Get from bucket
	var v []byte
	boltTest.DB.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("test"))
		v = b.Get([]byte("hello"))
		return nil
	})
	if v == nil {
		t.Error("Cannot retrive values from BOLTDB")
	}
	if string(v) != "world" {
		t.Error("BoltDB not storing values correctly")
	}

	boltTest.Mutex.RUnlock()
	boltTest.Mutex.Lock()

	//Delete from bucket
	err = boltTest.DB.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("test"))
		err = b.Delete([]byte("hello"))
		return err
	})
	if err != nil {
		t.Error(err)
	}

	//Delete test bucket
	err = boltTest.DB.Update(func(tx *bolt.Tx) error {
		err := tx.DeleteBucket([]byte("test"))
		return err
	})
	if err != nil {
		t.Error(err)
	}

	boltTest.Mutex.Unlock()

	boltTest.DB.Close()
}
<|endoftext|>


<commit_before>package svg // import "github.com/tdewolff/minify/svg"

import (
	"io"

	"github.com/tdewolff/buffer"
	"github.com/tdewolff/minify"
	xmlMinify "github.com/tdewolff/minify/xml"
	"github.com/tdewolff/parse"
	cssParse "github.com/tdewolff/parse/css"
	"github.com/tdewolff/parse/svg"
	"github.com/tdewolff/parse/xml"
)

var (
	ltBytes         = []byte("<")
	gtBytes         = []byte(">")
	voidBytes       = []byte("/>")
	isBytes         = []byte("=")
	spaceBytes      = []byte(" ")
	emptyBytes      = []byte("\"\"")
	endBytes        = []byte("</")
	CDATAStartBytes = []byte("<![CDATA[")
	CDATAEndBytes   = []byte("]]>")
)

////////////////////////////////////////////////////////////////

// Minify minifies XML files, it reads from r and writes to w.
// Removes unnecessary whitespace, tags, attributes, quotes and comments and typically saves 10% in size.
func Minify(m minify.Minifier, _ string, w io.Writer, r io.Reader) error {
	var tag svg.Hash

	attrMinifyBuffer := buffer.NewWriter(make([]byte, 0, 64))
	attrByteBuffer := make([]byte, 0, 64)

	z := xml.NewTokenizer(r)
	tb := xmlMinify.NewTokenBuffer(z)
	for {
		t := *tb.Shift()
		if t.TokenType == xml.CDATAToken {
			var useCDATA bool
			if t.Data, useCDATA = xmlMinify.EscapeCDATAVal(&attrByteBuffer, t.Data); !useCDATA {
				t.TokenType = xml.TextToken
			}
		}
		switch t.TokenType {
		case xml.ErrorToken:
			if z.Err() == io.EOF {
				return nil
			}
			return z.Err()
		case xml.TextToken:
			t.Data = parse.ReplaceMultiple(parse.Trim(t.Data, parse.IsWhitespace), parse.IsWhitespace, ' ')
			if tag == svg.Style && len(t.Data) > 0 {
				if err := m.Minify("text/css", w, buffer.NewReader(t.Data)); err != nil {
					if err == minify.ErrNotExist { // no minifier, write the original
						if _, err := w.Write(t.Data); err != nil {
							return err
						}
					} else {
						return err
					}
				}
			} else if _, err := w.Write(t.Data); err != nil {
				return err
			}
		case xml.CDATAToken:
			if _, err := w.Write(CDATAStartBytes); err != nil {
				return err
			}
			t.Data = parse.ReplaceMultiple(parse.Trim(t.Data, parse.IsWhitespace), parse.IsWhitespace, ' ')
			if tag == svg.Style && len(t.Data) > 0 {
				if err := m.Minify("text/css", w, buffer.NewReader(t.Data)); err != nil {
					if err == minify.ErrNotExist { // no minifier, write the original
						if _, err := w.Write(t.Data); err != nil {
							return err
						}
					} else {
						return err
					}
				}
			} else if _, err := w.Write(t.Data); err != nil {
				return err
			}
			if _, err := w.Write(CDATAEndBytes); err != nil {
				return err
			}
		case xml.StartTagToken:
			if _, err := w.Write(ltBytes); err != nil {
				return err
			}
			if _, err := w.Write(t.Data); err != nil {
				return err
			}
			tag = svg.ToHash(t.Data)
		case xml.StartTagPIToken:
			for {
				if t := *tb.Shift(); t.TokenType != xml.StartTagClosePIToken {
					break
				}
			}
		case xml.AttributeToken:
			if len(t.AttrVal) < 2 {
				continue
			}
			attr := svg.ToHash(t.Data)
			val := parse.ReplaceMultiple(parse.Trim(t.AttrVal[1:len(t.AttrVal)-1], parse.IsWhitespace), parse.IsWhitespace, ' ')
			if tag == svg.Svg && attr == svg.Version {
				continue
			}

			if _, err := w.Write(spaceBytes); err != nil {
				return err
			}
			if _, err := w.Write(t.Data); err != nil {
				return err
			}
			if _, err := w.Write(isBytes); err != nil {
				return err
			}

			if attr == svg.Style {
				attrMinifyBuffer.Reset()
				if m.Minify("text/css;inline=1", attrMinifyBuffer, buffer.NewReader(val)) == nil {
					val = attrMinifyBuffer.Bytes()
				}
			} else if tag == svg.Path && attr == svg.D {
				val = shortenPathData(val)
			} else if num, dim, ok := cssParse.SplitNumberDimension(val); ok {
				num = minify.Number(num)
				if len(num) == 1 && num[0] == '0' {
					val = num
				} else {
					if len(dim) > 1 { // only percentage is length 1
						parse.ToLower(dim)
					}
					val = append(num, dim...)
				}
			}

			// prefer single or double quotes depending on what occurs more often in value
			val = xmlMinify.EscapeAttrVal(&attrByteBuffer, val)
			if _, err := w.Write(val); err != nil {
				return err
			}
		case xml.StartTagCloseToken:
			next := tb.Peek(0)
			skipExtra := false
			if next.TokenType == xml.TextToken && parse.IsAllWhitespace(next.Data) {
				next = tb.Peek(1)
				skipExtra = true
			}
			if next.TokenType == xml.EndTagToken {
				// collapse empty tags to single void tag
				tb.Shift()
				if skipExtra {
					tb.Shift()
				}
				if _, err := w.Write(voidBytes); err != nil {
					return err
				}
			} else {
				if _, err := w.Write(gtBytes); err != nil {
					return err
				}
			}
		case xml.StartTagCloseVoidToken:
			if _, err := w.Write(voidBytes); err != nil {
				return err
			}
		case xml.EndTagToken:
			if _, err := w.Write(endBytes); err != nil {
				return err
			}
			if _, err := w.Write(t.Data); err != nil {
				return err
			}
			if _, err := w.Write(gtBytes); err != nil {
				return err
			}
		}
	}
}

func shortenPathData(b []byte) []byte {
	cmd := byte(0)
	prevDigit := false
	prevDigitRequiresSpace := true
	j := 0
	start := 0
	for i := 0; i < len(b); i++ {
		c := b[i]
		if c == ' ' || c == ',' || c == '\t' || c == '\n' || c == '\r' {
			if start != 0 {
				j += copy(b[j:], b[start:i])
			} else {
				j += i
			}
			start = i + 1
		} else if n, ok := parse.Number(b[i:]); ok {
			if start != 0 {
				j += copy(b[j:], b[start:i])
			} else {
				j += i
			}
			num := minify.Number(b[i : i+n])
			if prevDigit && (num[0] >= '0' && num[0] <= '9' || num[0] == '.' && prevDigitRequiresSpace) {
				b[j] = ' '
				j++
			}
			prevDigit = true
			prevDigitRequiresSpace = true
			for _, c := range num {
				if c == '.' || c == 'e' || c == 'E' {
					prevDigitRequiresSpace = false
					break
				}
			}
			j += copy(b[j:], num)
			start = i + n
			i += n - 1
		} else {
			if cmd == c {
				if start != 0 {
					j += copy(b[j:], b[start:i])
				} else {
					j += i
				}
				start = i + 1
			} else {
				cmd = c
				prevDigit = false
			}
		}
	}
	if start != 0 {
		j += copy(b[j:], b[start:])
		return b[:j]
	}
	return b
}
<commit_msg>parse.Number returns only the length now, not ok<commit_after>package svg // import "github.com/tdewolff/minify/svg"

import (
	"io"

	"github.com/tdewolff/buffer"
	"github.com/tdewolff/minify"
	xmlMinify "github.com/tdewolff/minify/xml"
	"github.com/tdewolff/parse"
	cssParse "github.com/tdewolff/parse/css"
	"github.com/tdewolff/parse/svg"
	"github.com/tdewolff/parse/xml"
)

var (
	ltBytes         = []byte("<")
	gtBytes         = []byte(">")
	voidBytes       = []byte("/>")
	isBytes         = []byte("=")
	spaceBytes      = []byte(" ")
	emptyBytes      = []byte("\"\"")
	endBytes        = []byte("</")
	CDATAStartBytes = []byte("<![CDATA[")
	CDATAEndBytes   = []byte("]]>")
)

////////////////////////////////////////////////////////////////

// Minify minifies XML files, it reads from r and writes to w.
// Removes unnecessary whitespace, tags, attributes, quotes and comments and typically saves 10% in size.
func Minify(m minify.Minifier, _ string, w io.Writer, r io.Reader) error {
	var tag svg.Hash

	attrMinifyBuffer := buffer.NewWriter(make([]byte, 0, 64))
	attrByteBuffer := make([]byte, 0, 64)

	z := xml.NewTokenizer(r)
	tb := xmlMinify.NewTokenBuffer(z)
	for {
		t := *tb.Shift()
		if t.TokenType == xml.CDATAToken {
			var useCDATA bool
			if t.Data, useCDATA = xmlMinify.EscapeCDATAVal(&attrByteBuffer, t.Data); !useCDATA {
				t.TokenType = xml.TextToken
			}
		}
		switch t.TokenType {
		case xml.ErrorToken:
			if z.Err() == io.EOF {
				return nil
			}
			return z.Err()
		case xml.TextToken:
			t.Data = parse.ReplaceMultiple(parse.Trim(t.Data, parse.IsWhitespace), parse.IsWhitespace, ' ')
			if tag == svg.Style && len(t.Data) > 0 {
				if err := m.Minify("text/css", w, buffer.NewReader(t.Data)); err != nil {
					if err == minify.ErrNotExist { // no minifier, write the original
						if _, err := w.Write(t.Data); err != nil {
							return err
						}
					} else {
						return err
					}
				}
			} else if _, err := w.Write(t.Data); err != nil {
				return err
			}
		case xml.CDATAToken:
			if _, err := w.Write(CDATAStartBytes); err != nil {
				return err
			}
			t.Data = parse.ReplaceMultiple(parse.Trim(t.Data, parse.IsWhitespace), parse.IsWhitespace, ' ')
			if tag == svg.Style && len(t.Data) > 0 {
				if err := m.Minify("text/css", w, buffer.NewReader(t.Data)); err != nil {
					if err == minify.ErrNotExist { // no minifier, write the original
						if _, err := w.Write(t.Data); err != nil {
							return err
						}
					} else {
						return err
					}
				}
			} else if _, err := w.Write(t.Data); err != nil {
				return err
			}
			if _, err := w.Write(CDATAEndBytes); err != nil {
				return err
			}
		case xml.StartTagToken:
			if _, err := w.Write(ltBytes); err != nil {
				return err
			}
			if _, err := w.Write(t.Data); err != nil {
				return err
			}
			tag = svg.ToHash(t.Data)
		case xml.StartTagPIToken:
			for {
				if t := *tb.Shift(); t.TokenType != xml.StartTagClosePIToken {
					break
				}
			}
		case xml.AttributeToken:
			if len(t.AttrVal) < 2 {
				continue
			}
			attr := svg.ToHash(t.Data)
			val := parse.ReplaceMultiple(parse.Trim(t.AttrVal[1:len(t.AttrVal)-1], parse.IsWhitespace), parse.IsWhitespace, ' ')
			if tag == svg.Svg && attr == svg.Version {
				continue
			}

			if _, err := w.Write(spaceBytes); err != nil {
				return err
			}
			if _, err := w.Write(t.Data); err != nil {
				return err
			}
			if _, err := w.Write(isBytes); err != nil {
				return err
			}

			if attr == svg.Style {
				attrMinifyBuffer.Reset()
				if m.Minify("text/css;inline=1", attrMinifyBuffer, buffer.NewReader(val)) == nil {
					val = attrMinifyBuffer.Bytes()
				}
			} else if tag == svg.Path && attr == svg.D {
				val = shortenPathData(val)
			} else if num, dim, ok := cssParse.SplitNumberDimension(val); ok {
				num = minify.Number(num)
				if len(num) == 1 && num[0] == '0' {
					val = num
				} else {
					if len(dim) > 1 { // only percentage is length 1
						parse.ToLower(dim)
					}
					val = append(num, dim...)
				}
			}

			// prefer single or double quotes depending on what occurs more often in value
			val = xmlMinify.EscapeAttrVal(&attrByteBuffer, val)
			if _, err := w.Write(val); err != nil {
				return err
			}
		case xml.StartTagCloseToken:
			next := tb.Peek(0)
			skipExtra := false
			if next.TokenType == xml.TextToken && parse.IsAllWhitespace(next.Data) {
				next = tb.Peek(1)
				skipExtra = true
			}
			if next.TokenType == xml.EndTagToken {
				// collapse empty tags to single void tag
				tb.Shift()
				if skipExtra {
					tb.Shift()
				}
				if _, err := w.Write(voidBytes); err != nil {
					return err
				}
			} else {
				if _, err := w.Write(gtBytes); err != nil {
					return err
				}
			}
		case xml.StartTagCloseVoidToken:
			if _, err := w.Write(voidBytes); err != nil {
				return err
			}
		case xml.EndTagToken:
			if _, err := w.Write(endBytes); err != nil {
				return err
			}
			if _, err := w.Write(t.Data); err != nil {
				return err
			}
			if _, err := w.Write(gtBytes); err != nil {
				return err
			}
		}
	}
}

func shortenPathData(b []byte) []byte {
	cmd := byte(0)
	prevDigit := false
	prevDigitRequiresSpace := true
	j := 0
	start := 0
	for i := 0; i < len(b); i++ {
		c := b[i]
		if c == ' ' || c == ',' || c == '\t' || c == '\n' || c == '\r' {
			if start != 0 {
				j += copy(b[j:], b[start:i])
			} else {
				j += i
			}
			start = i + 1
		} else if n := parse.Number(b[i:]); n > 0 {
			if start != 0 {
				j += copy(b[j:], b[start:i])
			} else {
				j += i
			}
			num := minify.Number(b[i : i+n])
			if prevDigit && (num[0] >= '0' && num[0] <= '9' || num[0] == '.' && prevDigitRequiresSpace) {
				b[j] = ' '
				j++
			}
			prevDigit = true
			prevDigitRequiresSpace = true
			for _, c := range num {
				if c == '.' || c == 'e' || c == 'E' {
					prevDigitRequiresSpace = false
					break
				}
			}
			j += copy(b[j:], num)
			start = i + n
			i += n - 1
		} else {
			if cmd == c {
				if start != 0 {
					j += copy(b[j:], b[start:i])
				} else {
					j += i
				}
				start = i + 1
			} else {
				cmd = c
				prevDigit = false
			}
		}
	}
	if start != 0 {
		j += copy(b[j:], b[start:])
		return b[:j]
	}
	return b
}
<|endoftext|>