<commit_before>package goyaml

// #include "helpers.h"
import "C"

import (
    "unsafe"
    "reflect"
    "strconv"
)

const (
    documentNode = 1 << iota
    mappingNode
    sequenceNode
    scalarNode
    aliasNode
)

type node struct {
    kind int
    line, column int
    tag string
    value string
    implicit bool
    children []*node
    anchors map[string]*node
}

func GoYString(s *C.yaml_char_t) string {
    return C.GoString((*C.char)(unsafe.Pointer(s)))
}

// ----------------------------------------------------------------------------
// Parser, produces a node tree out of a libyaml event stream.

type parser struct {
    parser C.yaml_parser_t
    event C.yaml_event_t
    doc *node
}

func newParser(b []byte) *parser {
    p := parser{}
    if C.yaml_parser_initialize(&p.parser) == 0 {
        panic("Failed to initialize YAML emitter")
    }

    if len(b) == 0 {
        b = []byte{'\n'}
    }

    // How unsafe is this really?  Will this break if the GC becomes compacting?
    // Probably not, otherwise that would likely break &parse below as well.
    input := (*C.uchar)(unsafe.Pointer(&b[0]))
    C.yaml_parser_set_input_string(&p.parser, input, (C.size_t)(len(b)))

    p.skip()
    if p.event._type != C.YAML_STREAM_START_EVENT {
        panic("Expected stream start event, got " +
              strconv.Itoa(int(p.event._type)))
    }
    p.skip()
    return &p
}

func (p *parser) destroy() {
    if p.event._type != C.YAML_NO_EVENT {
        C.yaml_event_delete(&p.event)
    }
    C.yaml_parser_delete(&p.parser)
}

func (p *parser) skip() {
    if p.event._type != C.YAML_NO_EVENT {
        if p.event._type == C.YAML_STREAM_END_EVENT {
            panic("Attempted to go past the end of stream. Corrupted value?")
        }
        C.yaml_event_delete(&p.event)
    }
    if C.yaml_parser_parse(&p.parser, &p.event) == 0 {
        p.fail()
    }
}

func (p *parser) fail() {
    var where string
    var line int
    if p.parser.problem_mark.line != 0 {
        line = int(C.int(p.parser.problem_mark.line))
    } else if p.parser.context_mark.line != 0 {
        line = int(C.int(p.parser.context_mark.line))
    }
    if line != 0 {
        where = "line " + strconv.Itoa(line) + ": "
    }
    var msg string
    if p.parser.problem != nil {
        msg = C.GoString(p.parser.problem)
    } else {
        msg = "Unknown problem parsing YAML content"
    }
    panic(where + msg)
}

func (p *parser) anchor(n *node, anchor *C.yaml_char_t) {
    if anchor != nil {
        p.doc.anchors[GoYString(anchor)] = n
    }
}

func (p *parser) parse() *node {
    switch p.event._type {
    case C.YAML_SCALAR_EVENT:
        return p.scalar()
    case C.YAML_ALIAS_EVENT:
        return p.alias()
    case C.YAML_MAPPING_START_EVENT:
        return p.mapping()
    case C.YAML_SEQUENCE_START_EVENT:
        return p.sequence()
    case C.YAML_DOCUMENT_START_EVENT:
        return p.document()
    case C.YAML_STREAM_END_EVENT:
        // Happens when attempting to decode an empty buffer.
        return nil
    default:
        panic("Attempted to parse unknown event: " +
              strconv.Itoa(int(p.event._type)))
    }
    panic("Unreachable")
}

func (p *parser) node(kind int) *node {
    return &node{kind: kind,
                 line: int(C.int(p.event.start_mark.line)),
                 column: int(C.int(p.event.start_mark.column))}
}

func (p *parser) document() *node {
    n := p.node(documentNode)
    n.anchors = make(map[string]*node)
    p.doc = n
    p.skip()
    n.children = append(n.children, p.parse())
    if p.event._type != C.YAML_DOCUMENT_END_EVENT {
        panic("Expected end of document event but got " +
              strconv.Itoa(int(p.event._type)))
    }
    p.skip()
    return n
}

func (p *parser) alias() *node {
    alias := C.event_alias(&p.event)
    n := p.node(aliasNode)
    n.value = GoYString(alias.anchor)
    p.skip()
    return n
}

func (p *parser) scalar() *node {
    scalar := C.event_scalar(&p.event)
    n := p.node(scalarNode)
    n.value = GoYString(scalar.value)
    n.tag = GoYString(scalar.tag)
    n.implicit = (scalar.plain_implicit != 0)
    p.anchor(n, scalar.anchor)
    p.skip()
    return n
}

func (p *parser) sequence() *node {
    n := p.node(sequenceNode)
    p.anchor(n, C.event_sequence_start(&p.event).anchor)
    p.skip()
    for p.event._type != C.YAML_SEQUENCE_END_EVENT {
        n.children = append(n.children, p.parse())
    }
    p.skip()
    return n
}

func (p *parser) mapping() *node {
    n := p.node(mappingNode)
    p.anchor(n, C.event_mapping_start(&p.event).anchor)
    p.skip()
    for p.event._type != C.YAML_MAPPING_END_EVENT {
        n.children = append(n.children, p.parse(), p.parse())
    }
    p.skip()
    return n
}

// ----------------------------------------------------------------------------
// Decoder, unmarshals a node into a provided value.

type decoder struct {
    doc *node
    aliases map[string]bool
}

func newDecoder() *decoder {
    d := &decoder{}
    d.aliases = make(map[string]bool)
    return d
}

// d.setter deals with setters and pointer dereferencing and initialization.
//
// It's a slightly convoluted case to handle properly:
//
// - Nil pointers should be zeroed out, unless being set to nil
// - We don't know at this point yet what's the value to SetYAML() with.
// - We can't separate pointer deref/init and setter checking, because
//   a setter may be found while going down a pointer chain.
//
// Thus, here is how it takes care of it:
//
// - out is provided as a pointer, so that it can be replaced.
// - when looking at a non-setter ptr, *out=ptr.Elem(), unless tag=!!null
// - when a setter is found, *out=interface{}, and a set() function is
//   returned to call SetYAML() with the value of *out once it's defined.
//
func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()) {
    again := true
    for again {
        again = false
        setter, _ := (*out).Interface().(Setter)
        if tag != "!!null" || setter != nil {
            if pv, ok := (*out).(*reflect.PtrValue); ok {
                if pv.IsNil() {
                    *out = reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem())
                    pv.PointTo(*out)
                } else {
                    *out = pv.Elem()
                }
                setter, _ = pv.Interface().(Setter)
                again = true
            }
        }
        if setter != nil {
            var arg interface{}
            *out = reflect.NewValue(&arg).(*reflect.PtrValue).Elem()
            return func() {
                *good = setter.SetYAML(tag, arg)
            }
        }
    }
    return nil
}

func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
    switch n.kind {
    case documentNode:
        good = d.document(n, out)
    case scalarNode:
        good = d.scalar(n, out)
    case aliasNode:
        good = d.alias(n, out)
    case mappingNode:
        good = d.mapping(n, out)
    case sequenceNode:
        good = d.sequence(n, out)
    default:
        panic("Internal error: unknown node kind: " + strconv.Itoa(n.kind))
    }
    return
}

func (d *decoder) document(n *node, out reflect.Value) (good bool) {
    if len(n.children) == 1 {
        d.doc = n
        d.unmarshal(n.children[0], out)
        return true
    }
    return false
}

func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
    an, ok := d.doc.anchors[n.value]
    if !ok {
        panic("Unknown anchor '" + n.value + "' referenced")
    }
    if d.aliases[n.value] {
        panic("Anchor '" + n.value + "' value contains itself")
    }
    d.aliases[n.value] = true
    good = d.unmarshal(an, out)
    d.aliases[n.value] = false, false
    return good
}

func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
    var tag string
    var resolved interface{}
    if n.tag == "" && !n.implicit {
        resolved = n.value
    } else {
        tag, resolved = resolve(n.tag, n.value)
        if set := d.setter(tag, &out, &good); set != nil {
            defer set()
        }
    }
    switch out := out.(type) {
    case *reflect.StringValue:
        out.Set(n.value)
        good = true
    case *reflect.InterfaceValue:
        out.Set(reflect.NewValue(resolved))
        good = true
    case *reflect.IntValue:
        switch resolved := resolved.(type) {
        case int:
            if !out.Overflow(int64(resolved)) {
                out.Set(int64(resolved))
                good = true
            }
        case int64:
            if !out.Overflow(resolved) {
                out.Set(resolved)
                good = true
            }
        }
    case *reflect.UintValue:
        switch resolved := resolved.(type) {
        case int:
            if resolved >= 0 {
                out.Set(uint64(resolved))
                good = true
            }
        case int64:
            if resolved >= 0 {
                out.Set(uint64(resolved))
                good = true
            }
        }
    case *reflect.BoolValue:
        switch resolved := resolved.(type) {
        case bool:
            out.Set(resolved)
            good = true
        }
    case *reflect.FloatValue:
        switch resolved := resolved.(type) {
        case float:
            out.Set(float64(resolved))
            good = true
        }
    case *reflect.PtrValue:
        switch resolved := resolved.(type) {
        case nil:
            out.PointTo(nil)
            good = true
        }
    default:
        panic("Can't handle type yet: " + out.Type().String())
    }
    return good
}

func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
    if set := d.setter("!!seq", &out, &good); set != nil {
        defer set()
    }
    if iface, ok := out.(*reflect.InterfaceValue); ok {
        // No type hints. Will have to use a generic sequence.
        out = reflect.NewValue(make([]interface{}, 0))
        iface.SetValue(out)
    }

    sv, ok := out.(*reflect.SliceValue)
    if !ok {
        return false
    }
    st := sv.Type().(*reflect.SliceType)
    et := st.Elem()

    l := len(n.children)
    for i := 0; i < l; i++ {
        e := reflect.MakeZero(et)
        if ok := d.unmarshal(n.children[i], e); ok {
            sv.SetValue(reflect.Append(sv, e))
        }
    }
    return true
}

func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
    if set := d.setter("!!map", &out, &good); set != nil {
        defer set()
    }
    if s, ok := out.(*reflect.StructValue); ok {
        return d.mappingStruct(n, s)
    }

    if iface, ok := out.(*reflect.InterfaceValue); ok {
        // No type hints. Will have to use a generic map.
        out = reflect.NewValue(make(map[interface{}]interface{}))
        iface.SetValue(out)
    }

    mv, ok := out.(*reflect.MapValue)
    if !ok {
        return false
    }
    mt := mv.Type().(*reflect.MapType)
    kt := mt.Key()
    et := mt.Elem()

    l := len(n.children)
    for i := 0; i < l; i += 2 {
        k := reflect.MakeZero(kt)
        if d.unmarshal(n.children[i], k) {
            e := reflect.MakeZero(et)
            if d.unmarshal(n.children[i+1], e) {
                mv.SetElem(k, e)
            }
        }
    }
    return true
}

func (d *decoder) mappingStruct(n *node, out *reflect.StructValue) (good bool) {
    fields, err := getStructFields(out.Type().(*reflect.StructType))
    if err != nil {
        panic(err)
    }
    name := reflect.NewValue("").(*reflect.StringValue)
    fieldsMap := fields.Map
    l := len(n.children)
    for i := 0; i < l; i += 2 {
        if !d.unmarshal(n.children[i], name) {
            continue
        }
        if info, ok := fieldsMap[name.Get()]; ok {
            d.unmarshal(n.children[i+1], out.Field(info.Num))
        }
    }
    return true
}
<commit_msg>Unexport GoYString.<commit_after>package goyaml

// #include "helpers.h"
import "C"

import (
    "unsafe"
    "reflect"
    "strconv"
)

const (
    documentNode = 1 << iota
    mappingNode
    sequenceNode
    scalarNode
    aliasNode
)

type node struct {
    kind int
    line, column int
    tag string
    value string
    implicit bool
    children []*node
    anchors map[string]*node
}

func stry(s *C.yaml_char_t) string {
    return C.GoString((*C.char)(unsafe.Pointer(s)))
}

// ----------------------------------------------------------------------------
// Parser, produces a node tree out of a libyaml event stream.

type parser struct {
    parser C.yaml_parser_t
    event C.yaml_event_t
    doc *node
}

func newParser(b []byte) *parser {
    p := parser{}
    if C.yaml_parser_initialize(&p.parser) == 0 {
        panic("Failed to initialize YAML emitter")
    }

    if len(b) == 0 {
        b = []byte{'\n'}
    }

    // How unsafe is this really?  Will this break if the GC becomes compacting?
    // Probably not, otherwise that would likely break &parse below as well.
    input := (*C.uchar)(unsafe.Pointer(&b[0]))
    C.yaml_parser_set_input_string(&p.parser, input, (C.size_t)(len(b)))

    p.skip()
    if p.event._type != C.YAML_STREAM_START_EVENT {
        panic("Expected stream start event, got " +
              strconv.Itoa(int(p.event._type)))
    }
    p.skip()
    return &p
}

func (p *parser) destroy() {
    if p.event._type != C.YAML_NO_EVENT {
        C.yaml_event_delete(&p.event)
    }
    C.yaml_parser_delete(&p.parser)
}

func (p *parser) skip() {
    if p.event._type != C.YAML_NO_EVENT {
        if p.event._type == C.YAML_STREAM_END_EVENT {
            panic("Attempted to go past the end of stream. Corrupted value?")
        }
        C.yaml_event_delete(&p.event)
    }
    if C.yaml_parser_parse(&p.parser, &p.event) == 0 {
        p.fail()
    }
}

func (p *parser) fail() {
    var where string
    var line int
    if p.parser.problem_mark.line != 0 {
        line = int(C.int(p.parser.problem_mark.line))
    } else if p.parser.context_mark.line != 0 {
        line = int(C.int(p.parser.context_mark.line))
    }
    if line != 0 {
        where = "line " + strconv.Itoa(line) + ": "
    }
    var msg string
    if p.parser.problem != nil {
        msg = C.GoString(p.parser.problem)
    } else {
        msg = "Unknown problem parsing YAML content"
    }
    panic(where + msg)
}

func (p *parser) anchor(n *node, anchor *C.yaml_char_t) {
    if anchor != nil {
        p.doc.anchors[stry(anchor)] = n
    }
}

func (p *parser) parse() *node {
    switch p.event._type {
    case C.YAML_SCALAR_EVENT:
        return p.scalar()
    case C.YAML_ALIAS_EVENT:
        return p.alias()
    case C.YAML_MAPPING_START_EVENT:
        return p.mapping()
    case C.YAML_SEQUENCE_START_EVENT:
        return p.sequence()
    case C.YAML_DOCUMENT_START_EVENT:
        return p.document()
    case C.YAML_STREAM_END_EVENT:
        // Happens when attempting to decode an empty buffer.
        return nil
    default:
        panic("Attempted to parse unknown event: " +
              strconv.Itoa(int(p.event._type)))
    }
    panic("Unreachable")
}

func (p *parser) node(kind int) *node {
    return &node{kind: kind,
                 line: int(C.int(p.event.start_mark.line)),
                 column: int(C.int(p.event.start_mark.column))}
}

func (p *parser) document() *node {
    n := p.node(documentNode)
    n.anchors = make(map[string]*node)
    p.doc = n
    p.skip()
    n.children = append(n.children, p.parse())
    if p.event._type != C.YAML_DOCUMENT_END_EVENT {
        panic("Expected end of document event but got " +
              strconv.Itoa(int(p.event._type)))
    }
    p.skip()
    return n
}

func (p *parser) alias() *node {
    alias := C.event_alias(&p.event)
    n := p.node(aliasNode)
    n.value = stry(alias.anchor)
    p.skip()
    return n
}

func (p *parser) scalar() *node {
    scalar := C.event_scalar(&p.event)
    n := p.node(scalarNode)
    n.value = stry(scalar.value)
    n.tag = stry(scalar.tag)
    n.implicit = (scalar.plain_implicit != 0)
    p.anchor(n, scalar.anchor)
    p.skip()
    return n
}

func (p *parser) sequence() *node {
    n := p.node(sequenceNode)
    p.anchor(n, C.event_sequence_start(&p.event).anchor)
    p.skip()
    for p.event._type != C.YAML_SEQUENCE_END_EVENT {
        n.children = append(n.children, p.parse())
    }
    p.skip()
    return n
}

func (p *parser) mapping() *node {
    n := p.node(mappingNode)
    p.anchor(n, C.event_mapping_start(&p.event).anchor)
    p.skip()
    for p.event._type != C.YAML_MAPPING_END_EVENT {
        n.children = append(n.children, p.parse(), p.parse())
    }
    p.skip()
    return n
}

// ----------------------------------------------------------------------------
// Decoder, unmarshals a node into a provided value.

type decoder struct {
    doc *node
    aliases map[string]bool
}

func newDecoder() *decoder {
    d := &decoder{}
    d.aliases = make(map[string]bool)
    return d
}

// d.setter deals with setters and pointer dereferencing and initialization.
//
// It's a slightly convoluted case to handle properly:
//
// - Nil pointers should be zeroed out, unless being set to nil
// - We don't know at this point yet what's the value to SetYAML() with.
// - We can't separate pointer deref/init and setter checking, because
//   a setter may be found while going down a pointer chain.
//
// Thus, here is how it takes care of it:
//
// - out is provided as a pointer, so that it can be replaced.
// - when looking at a non-setter ptr, *out=ptr.Elem(), unless tag=!!null
// - when a setter is found, *out=interface{}, and a set() function is
//   returned to call SetYAML() with the value of *out once it's defined.
//
func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()) {
    again := true
    for again {
        again = false
        setter, _ := (*out).Interface().(Setter)
        if tag != "!!null" || setter != nil {
            if pv, ok := (*out).(*reflect.PtrValue); ok {
                if pv.IsNil() {
                    *out = reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem())
                    pv.PointTo(*out)
                } else {
                    *out = pv.Elem()
                }
                setter, _ = pv.Interface().(Setter)
                again = true
            }
        }
        if setter != nil {
            var arg interface{}
            *out = reflect.NewValue(&arg).(*reflect.PtrValue).Elem()
            return func() {
                *good = setter.SetYAML(tag, arg)
            }
        }
    }
    return nil
}

func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
    switch n.kind {
    case documentNode:
        good = d.document(n, out)
    case scalarNode:
        good = d.scalar(n, out)
    case aliasNode:
        good = d.alias(n, out)
    case mappingNode:
        good = d.mapping(n, out)
    case sequenceNode:
        good = d.sequence(n, out)
    default:
        panic("Internal error: unknown node kind: " + strconv.Itoa(n.kind))
    }
    return
}

func (d *decoder) document(n *node, out reflect.Value) (good bool) {
    if len(n.children) == 1 {
        d.doc = n
        d.unmarshal(n.children[0], out)
        return true
    }
    return false
}

func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
    an, ok := d.doc.anchors[n.value]
    if !ok {
        panic("Unknown anchor '" + n.value + "' referenced")
    }
    if d.aliases[n.value] {
        panic("Anchor '" + n.value + "' value contains itself")
    }
    d.aliases[n.value] = true
    good = d.unmarshal(an, out)
    d.aliases[n.value] = false, false
    return good
}

func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
    var tag string
    var resolved interface{}
    if n.tag == "" && !n.implicit {
        resolved = n.value
    } else {
        tag, resolved = resolve(n.tag, n.value)
        if set := d.setter(tag, &out, &good); set != nil {
            defer set()
        }
    }
    switch out := out.(type) {
    case *reflect.StringValue:
        out.Set(n.value)
        good = true
    case *reflect.InterfaceValue:
        out.Set(reflect.NewValue(resolved))
        good = true
    case *reflect.IntValue:
        switch resolved := resolved.(type) {
        case int:
            if !out.Overflow(int64(resolved)) {
                out.Set(int64(resolved))
                good = true
            }
        case int64:
            if !out.Overflow(resolved) {
                out.Set(resolved)
                good = true
            }
        }
    case *reflect.UintValue:
        switch resolved := resolved.(type) {
        case int:
            if resolved >= 0 {
                out.Set(uint64(resolved))
                good = true
            }
        case int64:
            if resolved >= 0 {
                out.Set(uint64(resolved))
                good = true
            }
        }
    case *reflect.BoolValue:
        switch resolved := resolved.(type) {
        case bool:
            out.Set(resolved)
            good = true
        }
    case *reflect.FloatValue:
        switch resolved := resolved.(type) {
        case float:
            out.Set(float64(resolved))
            good = true
        }
    case *reflect.PtrValue:
        switch resolved := resolved.(type) {
        case nil:
            out.PointTo(nil)
            good = true
        }
    default:
        panic("Can't handle type yet: " + out.Type().String())
    }
    return good
}

func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
    if set := d.setter("!!seq", &out, &good); set != nil {
        defer set()
    }
    if iface, ok := out.(*reflect.InterfaceValue); ok {
        // No type hints. Will have to use a generic sequence.
        out = reflect.NewValue(make([]interface{}, 0))
        iface.SetValue(out)
    }

    sv, ok := out.(*reflect.SliceValue)
    if !ok {
        return false
    }
    st := sv.Type().(*reflect.SliceType)
    et := st.Elem()

    l := len(n.children)
    for i := 0; i < l; i++ {
        e := reflect.MakeZero(et)
        if ok := d.unmarshal(n.children[i], e); ok {
            sv.SetValue(reflect.Append(sv, e))
        }
    }
    return true
}

func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
    if set := d.setter("!!map", &out, &good); set != nil {
        defer set()
    }
    if s, ok := out.(*reflect.StructValue); ok {
        return d.mappingStruct(n, s)
    }

    if iface, ok := out.(*reflect.InterfaceValue); ok {
        // No type hints. Will have to use a generic map.
        out = reflect.NewValue(make(map[interface{}]interface{}))
        iface.SetValue(out)
    }

    mv, ok := out.(*reflect.MapValue)
    if !ok {
        return false
    }
    mt := mv.Type().(*reflect.MapType)
    kt := mt.Key()
    et := mt.Elem()

    l := len(n.children)
    for i := 0; i < l; i += 2 {
        k := reflect.MakeZero(kt)
        if d.unmarshal(n.children[i], k) {
            e := reflect.MakeZero(et)
            if d.unmarshal(n.children[i+1], e) {
                mv.SetElem(k, e)
            }
        }
    }
    return true
}

func (d *decoder) mappingStruct(n *node, out *reflect.StructValue) (good bool) {
    fields, err := getStructFields(out.Type().(*reflect.StructType))
    if err != nil {
        panic(err)
    }
    name := reflect.NewValue("").(*reflect.StringValue)
    fieldsMap := fields.Map
    l := len(n.children)
    for i := 0; i < l; i += 2 {
        if !d.unmarshal(n.children[i], name) {
            continue
        }
        if info, ok := fieldsMap[name.Get()]; ok {
            d.unmarshal(n.children[i+1], out.Field(info.Num))
        }
    }
    return true
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"runtime"
)

func main() {
}
<commit_msg>goblin install implemented<commit_after><|endoftext|>


<commit_before>// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff

package draw2d

import (
	"math"
)

type MatrixTransform [6]float64

const (
	epsilon = 1e-6
)

func (tr MatrixTransform) Determinant() float64 {
	return tr[0]*tr[3] - tr[1]*tr[2]
}

// Transform apply the Affine Matrix to points. It modify the points passed in parameter.
func (tr MatrixTransform) Transform(points []float64) {
	for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
		x := points[i]
		y := points[j]
		points[i] = x*tr[0] + y*tr[2] + tr[4]
		points[j] = x*tr[1] + y*tr[3] + tr[5]
	}
}

func (tr MatrixTransform) TransformPoint(x, y float64) (xres, yres float64) {
	xres = x*tr[0] + y*tr[2] + tr[4]
	yres = x*tr[1] + y*tr[3] + tr[5]
	return xres, yres
}

func minMax(x, y float64) (min, max float64) {
	if x > y {
		return y, x
	}
	return x, y
}

func (tr MatrixTransform) TransformRectangle(x0, y0, x2, y2 float64) (nx0, ny0, nx2, ny2 float64) {
	points := []float64{x0, y0, x2, y0, x2, y2, x0, y2}
	tr.Transform(points)
	points[0], points[2] = minMax(points[0], points[2])
	points[4], points[6] = minMax(points[4], points[6])
	points[1], points[3] = minMax(points[1], points[3])
	points[5], points[7] = minMax(points[5], points[7])

	nx0 = math.Min(points[0], points[4])
	ny0 = math.Min(points[1], points[5])
	nx2 = math.Max(points[2], points[6])
	ny2 = math.Max(points[3], points[7])
	return nx0, ny0, nx2, ny2
}

func (tr MatrixTransform) InverseTransform(points []float64) {
	d := tr.Determinant() // matrix determinant
	for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
		x := points[i]
		y := points[j]
		points[i] = ((x-tr[4])*tr[3] - (y-tr[5])*tr[2]) / d
		points[j] = ((y-tr[5])*tr[0] - (x-tr[4])*tr[1]) / d
	}
}

func (tr MatrixTransform) InverseTransformPoint(x, y float64) (xres, yres float64) {
	d := tr.Determinant() // matrix determinant
	xres = ((x-tr[4])*tr[3] - (y-tr[5])*tr[2]) / d
	yres = ((y-tr[5])*tr[0] - (x-tr[4])*tr[1]) / d
	return xres, yres
}

// ******************** Vector transformations ********************

func (tr MatrixTransform) VectorTransform(points []float64) {
	for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
		x := points[i]
		y := points[j]
		points[i] = x*tr[0] + y*tr[2]
		points[j] = x*tr[1] + y*tr[3]
	}
}

// ******************** Transformations creation ********************

/** Creates an identity transformation. */
func NewIdentityMatrix() MatrixTransform {
	return [6]float64{1, 0, 0, 1, 0, 0}
}

/**
 * Creates a transformation with a translation, that,
 * transform point1 into point2.
 */
func NewTranslationMatrix(tx, ty float64) MatrixTransform {
	return [6]float64{1, 0, 0, 1, tx, ty}
}

/**
 * Creates a transformation with a sx, sy scale factor
 */
func NewScaleMatrix(sx, sy float64) MatrixTransform {
	return [6]float64{sx, 0, 0, sy, 0, 0}
}

/**
 * Creates a rotation transformation.
 */
func NewRotationMatrix(angle float64) MatrixTransform {
	c := math.Cos(angle)
	s := math.Sin(angle)
	return [6]float64{c, s, -s, c, 0, 0}
}

/**
 * Creates a transformation, combining a scale and a translation, that transform rectangle1 into rectangle2.
 */
func NewMatrixTransform(rectangle1, rectangle2 [4]float64) MatrixTransform {
	xScale := (rectangle2[2] - rectangle2[0]) / (rectangle1[2] - rectangle1[0])
	yScale := (rectangle2[3] - rectangle2[1]) / (rectangle1[3] - rectangle1[1])
	xOffset := rectangle2[0] - (rectangle1[0] * xScale)
	yOffset := rectangle2[1] - (rectangle1[1] * yScale)
	return [6]float64{xScale, 0, 0, yScale, xOffset, yOffset}
}

// ******************** Transformations operations ********************

/**
 * Returns a transformation that is the inverse of the given transformation.
 */
func (tr MatrixTransform) GetInverseTransformation() MatrixTransform {
	d := tr.Determinant() // matrix determinant
	return [6]float64{
		tr[3] / d,
		-tr[1] / d,
		-tr[2] / d,
		tr[0] / d,
		(tr[2]*tr[5] - tr[3]*tr[4]) / d,
		(tr[1]*tr[4] - tr[0]*tr[5]) / d}
}

func (tr1 MatrixTransform) Multiply(tr2 MatrixTransform) MatrixTransform {
	return [6]float64{
		tr1[0]*tr2[0] + tr1[1]*tr2[2],
		tr1[1]*tr2[3] + tr1[0]*tr2[1],
		tr1[2]*tr2[0] + tr1[3]*tr2[2],
		tr1[3]*tr2[3] + tr1[2]*tr2[1],
		tr1[4]*tr2[0] + tr1[5]*tr2[2] + tr2[4],
		tr1[5]*tr2[3] + tr1[4]*tr2[1] + tr2[5]}
}

func (tr *MatrixTransform) Scale(sx, sy float64) *MatrixTransform {
	tr[0] = sx * tr[0]
	tr[1] = sx * tr[1]
	tr[2] = sy * tr[2]
	tr[3] = sy * tr[3]
	return tr
}

func (tr *MatrixTransform) Translate(tx, ty float64) *MatrixTransform {
	tr[4] = tx*tr[0] + ty*tr[2] + tr[4]
	tr[5] = ty*tr[3] + tx*tr[1] + tr[5]
	return tr
}

func (tr *MatrixTransform) Rotate(angle float64) *MatrixTransform {
	c := math.Cos(angle)
	s := math.Sin(angle)
	t0 := c*tr[0] + s*tr[2]
	t1 := s*tr[3] + c*tr[1]
	t2 := c*tr[2] - s*tr[0]
	t3 := c*tr[3] - s*tr[1]
	tr[0] = t0
	tr[1] = t1
	tr[2] = t2
	tr[3] = t3
	return tr
}

func (tr MatrixTransform) GetTranslation() (x, y float64) {
	return tr[4], tr[5]
}

func (tr MatrixTransform) GetScaling() (x, y float64) {
	return tr[0], tr[3]
}

func (tr MatrixTransform) GetScale() float64 {
	x := 0.707106781*tr[0] + 0.707106781*tr[1]
	y := 0.707106781*tr[2] + 0.707106781*tr[3]
	return math.Sqrt(x*x + y*y)
}

func (tr MatrixTransform) GetMaxAbsScaling() (s float64) {
	sx := math.Abs(tr[0])
	sy := math.Abs(tr[3])
	if sx > sy {
		return sx
	}
	return sy
}

func (tr MatrixTransform) GetMinAbsScaling() (s float64) {
	sx := math.Abs(tr[0])
	sy := math.Abs(tr[3])
	if sx > sy {
		return sy
	}
	return sx
}

// ******************** Testing ********************

/**
 * Tests if a two transformation are equal. A tolerance is applied when
 * comparing matrix elements.
 */
func (tr1 MatrixTransform) Equals(tr2 MatrixTransform) bool {
	for i := 0; i < 6; i = i + 1 {
		if !fequals(tr1[i], tr2[i]) {
			return false
		}
	}
	return true
}

/**
 * Tests if a transformation is the identity transformation. A tolerance
 * is applied when comparing matrix elements.
 */
func (tr MatrixTransform) IsIdentity() bool {
	return fequals(tr[4], 0) && fequals(tr[5], 0) && tr.IsTranslation()
}

/**
 * Tests if a transformation is is a pure translation. A tolerance
 * is applied when comparing matrix elements.
 */
func (tr MatrixTransform) IsTranslation() bool {
	return fequals(tr[0], 1) && fequals(tr[1], 0) && fequals(tr[2], 0) && fequals(tr[3], 1)
}

/**
 * Compares two floats.
 * return true if the distance between the two floats is less than epsilon, false otherwise
 */
func fequals(float1, float2 float64) bool {
	return math.Abs(float1-float2) <= epsilon
}

// Transformer apply the Matrix transformation tr
type Transformer struct {
	Tr        MatrixTransform
	Flattener Flattener
}

func (t Transformer) MoveTo(x, y float64) {
	u := x*t.Tr[0] + y*t.Tr[2] + t.Tr[4]
	v := x*t.Tr[1] + y*t.Tr[3] + t.Tr[5]
	t.Flattener.MoveTo(u, v)
}

func (t Transformer) LineTo(x, y float64) {
	u := x*t.Tr[0] + y*t.Tr[2] + t.Tr[4]
	v := x*t.Tr[1] + y*t.Tr[3] + t.Tr[5]
	t.Flattener.LineTo(u, v)
}

func (t Transformer) LineJoin() {
	t.Flattener.LineJoin()
}

func (t Transformer) Close() {
	t.Flattener.Close()
}

func (t Transformer) End() {
	t.Flattener.End()
}
<commit_msg>transform clean up<commit_after>// Copyright 2010 The draw2d Authors. All rights reserved.
// created: 21/11/2010 by Laurent Le Goff

package draw2d

import (
	"math"
)

type MatrixTransform [6]float64

const (
	epsilon = 1e-6
)

// Determinant compute the determinant of the matrix
func (tr MatrixTransform) Determinant() float64 {
	return tr[0]*tr[3] - tr[1]*tr[2]
}

// Transform apply the transformation matrix to points. It modify the points passed in parameter.
func (tr MatrixTransform) Transform(points []float64) {
	for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
		x := points[i]
		y := points[j]
		points[i] = x*tr[0] + y*tr[2] + tr[4]
		points[j] = x*tr[1] + y*tr[3] + tr[5]
	}
}

// TransformPoint apply the transformation matrix to point. It returns the point the transformed point.
func (tr MatrixTransform) TransformPoint(x, y float64) (xres, yres float64) {
	xres = x*tr[0] + y*tr[2] + tr[4]
	yres = x*tr[1] + y*tr[3] + tr[5]
	return xres, yres
}

func minMax(x, y float64) (min, max float64) {
	if x > y {
		return y, x
	}
	return x, y
}

// Transform apply the transformation matrix to the rectangle represented by the min and the max point of the rectangle
func (tr MatrixTransform) TransformRectangle(x0, y0, x2, y2 float64) (nx0, ny0, nx2, ny2 float64) {
	points := []float64{x0, y0, x2, y0, x2, y2, x0, y2}
	tr.Transform(points)
	points[0], points[2] = minMax(points[0], points[2])
	points[4], points[6] = minMax(points[4], points[6])
	points[1], points[3] = minMax(points[1], points[3])
	points[5], points[7] = minMax(points[5], points[7])

	nx0 = math.Min(points[0], points[4])
	ny0 = math.Min(points[1], points[5])
	nx2 = math.Max(points[2], points[6])
	ny2 = math.Max(points[3], points[7])
	return nx0, ny0, nx2, ny2
}

// InverseTransform apply the transformation inverse matrix to the rectangle represented by the min and the max point of the rectangle
func (tr MatrixTransform) InverseTransform(points []float64) {
	d := tr.Determinant() // matrix determinant
	for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
		x := points[i]
		y := points[j]
		points[i] = ((x-tr[4])*tr[3] - (y-tr[5])*tr[2]) / d
		points[j] = ((y-tr[5])*tr[0] - (x-tr[4])*tr[1]) / d
	}
}

// InverseTransformPoint apply the transformation inverse matrix to point. It returns the point the transformed point.
func (tr MatrixTransform) InverseTransformPoint(x, y float64) (xres, yres float64) {
	d := tr.Determinant() // matrix determinant
	xres = ((x-tr[4])*tr[3] - (y-tr[5])*tr[2]) / d
	yres = ((y-tr[5])*tr[0] - (x-tr[4])*tr[1]) / d
	return xres, yres
}

// VectorTransform apply the transformation matrix to points without using the translation parameter of the affine matrix.
// It modify the points passed in parameter.
func (tr MatrixTransform) VectorTransform(points []float64) {
	for i, j := 0, 1; j < len(points); i, j = i+2, j+2 {
		x := points[i]
		y := points[j]
		points[i] = x*tr[0] + y*tr[2]
		points[j] = x*tr[1] + y*tr[3]
	}
}

// NewIdentityMatrix creates an identity transformation matrix.
func NewIdentityMatrix() MatrixTransform {
	return [6]float64{1, 0, 0, 1, 0, 0}
}

// NewTranslationMatrix creates a transformation matrix with a translation tx and ty translation parameter
func NewTranslationMatrix(tx, ty float64) MatrixTransform {
	return [6]float64{1, 0, 0, 1, tx, ty}
}

// NewScaleMatrix creates a transformation matrix with a sx, sy scale factor
func NewScaleMatrix(sx, sy float64) MatrixTransform {
	return [6]float64{sx, 0, 0, sy, 0, 0}
}

// NewRotationMatrix creates a rotation transformation matrix. angle is in radian
func NewRotationMatrix(angle float64) MatrixTransform {
	c := math.Cos(angle)
	s := math.Sin(angle)
	return [6]float64{c, s, -s, c, 0, 0}
}

// NewMatrixTransform creates a transformation matrix, combining a scale and a translation, that transform rectangle1 into rectangle2.
func NewMatrixFromRects(rectangle1, rectangle2 [4]float64) MatrixTransform {
	xScale := (rectangle2[2] - rectangle2[0]) / (rectangle1[2] - rectangle1[0])
	yScale := (rectangle2[3] - rectangle2[1]) / (rectangle1[3] - rectangle1[1])
	xOffset := rectangle2[0] - (rectangle1[0] * xScale)
	yOffset := rectangle2[1] - (rectangle1[1] * yScale)
	return [6]float64{xScale, 0, 0, yScale, xOffset, yOffset}
}

// Inverse returns a matrix that is the inverse of the given matrix.
func (tr MatrixTransform) Inverse() MatrixTransform {
	d := tr.Determinant() // matrix determinant
	return [6]float64{
		tr[3] / d,
		-tr[1] / d,
		-tr[2] / d,
		tr[0] / d,
		(tr[2]*tr[5] - tr[3]*tr[4]) / d,
		(tr[1]*tr[4] - tr[0]*tr[5]) / d}
}

// Multiply Compose Matrix tr1 with tr2 returns the resulting matrix
func (tr1 MatrixTransform) Multiply(tr2 MatrixTransform) MatrixTransform {
	return [6]float64{
		tr1[0]*tr2[0] + tr1[1]*tr2[2],
		tr1[1]*tr2[3] + tr1[0]*tr2[1],
		tr1[2]*tr2[0] + tr1[3]*tr2[2],
		tr1[3]*tr2[3] + tr1[2]*tr2[1],
		tr1[4]*tr2[0] + tr1[5]*tr2[2] + tr2[4],
		tr1[5]*tr2[3] + tr1[4]*tr2[1] + tr2[5]}
}

// Scale add a scale to the matrix
func (tr *MatrixTransform) Scale(sx, sy float64) *MatrixTransform {
	tr[0] = sx * tr[0]
	tr[1] = sx * tr[1]
	tr[2] = sy * tr[2]
	tr[3] = sy * tr[3]
	return tr
}

// Translate add a translation to the matrix
func (tr *MatrixTransform) Translate(tx, ty float64) *MatrixTransform {
	tr[4] = tx*tr[0] + ty*tr[2] + tr[4]
	tr[5] = ty*tr[3] + tx*tr[1] + tr[5]
	return tr
}

// Rotate add a rotation to the matrix. angle is in radian
func (tr *MatrixTransform) Rotate(angle float64) *MatrixTransform {
	c := math.Cos(angle)
	s := math.Sin(angle)
	t0 := c*tr[0] + s*tr[2]
	t1 := s*tr[3] + c*tr[1]
	t2 := c*tr[2] - s*tr[0]
	t3 := c*tr[3] - s*tr[1]
	tr[0] = t0
	tr[1] = t1
	tr[2] = t2
	tr[3] = t3
	return tr
}

// GetTranslation
func (tr MatrixTransform) GetTranslation() (x, y float64) {
	return tr[4], tr[5]
}

// GetScaling
func (tr MatrixTransform) GetScaling() (x, y float64) {
	return tr[0], tr[3]
}

// GetScale computes the scale of the matrix
func (tr MatrixTransform) GetScale() float64 {
	x := 0.707106781*tr[0] + 0.707106781*tr[1]
	y := 0.707106781*tr[2] + 0.707106781*tr[3]
	return math.Sqrt(x*x + y*y)
}

func (tr MatrixTransform) GetMaxAbsScaling() (s float64) {
	sx := math.Abs(tr[0])
	sy := math.Abs(tr[3])
	if sx > sy {
		return sx
	}
	return sy
}

func (tr MatrixTransform) GetMinAbsScaling() (s float64) {
	sx := math.Abs(tr[0])
	sy := math.Abs(tr[3])
	if sx > sy {
		return sy
	}
	return sx
}

// ******************** Testing ********************

/**
 * Tests if a two transformation are equal. A tolerance is applied when
 * comparing matrix elements.
 */
func (tr1 MatrixTransform) Equals(tr2 MatrixTransform) bool {
	for i := 0; i < 6; i = i + 1 {
		if !fequals(tr1[i], tr2[i]) {
			return false
		}
	}
	return true
}

/**
 * Tests if a transformation is the identity transformation. A tolerance
 * is applied when comparing matrix elements.
 */
func (tr MatrixTransform) IsIdentity() bool {
	return fequals(tr[4], 0) && fequals(tr[5], 0) && tr.IsTranslation()
}

/**
 * Tests if a transformation is is a pure translation. A tolerance
 * is applied when comparing matrix elements.
 */
func (tr MatrixTransform) IsTranslation() bool {
	return fequals(tr[0], 1) && fequals(tr[1], 0) && fequals(tr[2], 0) && fequals(tr[3], 1)
}

/**
 * Compares two floats.
 * return true if the distance between the two floats is less than epsilon, false otherwise
 */
func fequals(float1, float2 float64) bool {
	return math.Abs(float1-float2) <= epsilon
}

// Transformer apply the Matrix transformation tr
type Transformer struct {
	Tr        MatrixTransform
	Flattener Flattener
}

func (t Transformer) MoveTo(x, y float64) {
	u := x*t.Tr[0] + y*t.Tr[2] + t.Tr[4]
	v := x*t.Tr[1] + y*t.Tr[3] + t.Tr[5]
	t.Flattener.MoveTo(u, v)
}

func (t Transformer) LineTo(x, y float64) {
	u := x*t.Tr[0] + y*t.Tr[2] + t.Tr[4]
	v := x*t.Tr[1] + y*t.Tr[3] + t.Tr[5]
	t.Flattener.LineTo(u, v)
}

func (t Transformer) LineJoin() {
	t.Flattener.LineJoin()
}

func (t Transformer) Close() {
	t.Flattener.Close()
}

func (t Transformer) End() {
	t.Flattener.End()
}
<|endoftext|>


<commit_before>package signals

import (
	"errors"
	"io"
	"net/http"
	"encoding/gob"
)
func init() {
	gob.Register(&Wave{})
}

const bufferSize = 16

// a PCM-Signal read, as required, from a URL.
// if queried for a property value for an x that is more than 32 samples lower than a previous query, will return zero.
type Wave struct{
	Shifted
	URL string
	reader io.Reader
}

func NewWave(URL string) (*Wave, error) {
	r, channels, bytes, rate, err := PCMReader(URL)
	if err!=nil {
		return nil,err
	}
	if channels != 1 {
		return nil, errors.New(URL+":Needs to be mono.")
	}
	b := make([]byte, bufferSize*bytes)
	n, err := r.Read(b)
	failOn(err)
	b=b[:n]
	switch bytes {
	case 1:
		return &Wave{Shifted{NewPCM8bit(rate, b),0},URL,r}, nil
	case 2:
		return &Wave{Shifted{NewPCM16bit(rate, b),0},URL,r}, nil
	case 3:
		return &Wave{Shifted{NewPCM24bit(rate, b),0},URL,r}, nil
	case 4:
		return &Wave{Shifted{NewPCM32bit(rate, b),0},URL,r}, nil
	case 6:
		return &Wave{Shifted{NewPCM48bit(rate, b),0},URL,r}, nil
	case 8:
		return &Wave{Shifted{NewPCM64bit(rate, b),0},URL,r}, nil
	}
	return nil, ErrWavParse{"Source bit rate not supported."}
}

func (s *Wave) property(offset x) y {
	if s.reader==nil{
		wav,err:=NewWave(s.URL)
		failOn(err)
		s.Shifted=wav.Shifted
		s.reader=wav.reader
	}
	for offset > s.MaxX() {
		// append available data onto the PCM slice.
		// also possibly shift off some data, shortening the PCM slice, retaining at least two buffer lengths.
		// semi-samples are read but not accessed by property
		switch st:=s.Shifted.Signal.(type) {
		case PCM8bit:
			sd:=PCM8bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize+n]
			if len(sd.Data)>bufferSize*3{
				sd.Data=sd.Data[bufferSize:]
				s.Shifted.Shift+=bufferSize*st.samplePeriod
			}
			s.Shifted=Shifted{sd,s.Shifted.Shift}
		case PCM16bit:
			sd:=PCM16bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize*2)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize*2:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize*2+n]
			if len(sd.Data)>bufferSize*2*3{
				sd.Data=sd.Data[bufferSize*2:]
				s.Shifted=Shifted{sd,s.Shifted.Shift+bufferSize*st.samplePeriod}
				}else{
				s.Shifted=Shifted{sd,s.Shifted.Shift}
			}
		case PCM24bit:
			sd:=PCM24bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize*3)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize*3:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize*3+n]
			if len(sd.Data)>bufferSize*3*3{
				sd.Data=sd.Data[bufferSize*3:]
				s.Shifted=Shifted{sd,s.Shifted.Shift+bufferSize*st.samplePeriod}
				}else{
				s.Shifted=Shifted{sd,s.Shifted.Shift}
			}
		case PCM32bit:
			sd:=PCM16bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize*4)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize*4:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize*4+n]
			if len(sd.Data)>bufferSize*4*3{
				sd.Data=sd.Data[bufferSize*4:]
				s.Shifted=Shifted{sd,s.Shifted.Shift+bufferSize*st.samplePeriod}
				}else{
				s.Shifted=Shifted{sd,s.Shifted.Shift}
			}
		case PCM48bit:
			sd:=PCM48bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize*6)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize*6:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize*6+n]
			if len(sd.Data)>bufferSize*6*3{
				sd.Data=sd.Data[bufferSize*6:]
				s.Shifted=Shifted{sd,s.Shifted.Shift+bufferSize*st.samplePeriod}
				}else{
				s.Shifted=Shifted{sd,s.Shifted.Shift}
			}
		case PCM64bit:
			sd:=PCM64bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize*8)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize*8:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize*8+n]
			if len(sd.Data)>bufferSize*8*3{
				sd.Data=sd.Data[bufferSize*8:]
				s.Shifted=Shifted{sd,s.Shifted.Shift+bufferSize*st.samplePeriod}
				}else{
				s.Shifted=Shifted{sd,s.Shifted.Shift}
			}
		}
	}
	return s.Shifted.property(offset)
}

//func updateShifted(s Shifted, r io.Reader, b *[]byte, blockSize int) (err error){
//	b=append(b,make([]byte,bufferSize*blockSize)...)
//	n, err := r.Read(b[len(b)-bufferSize*blockSize:])
//	failOn(err)
//	b=b[:len(b)-bufferSize*blockSize+n]
//	if len(b)>bufferSize*blockSize*3{
//		b=b[bufferSize*blockSize:]
//		s.Shift+=bufferSize*s.samplePeriod
//	}
//}

func PCMReader(source string) (io.Reader, uint16, uint16, uint32, error) {
	resp, err := http.Get(source)
	if err != nil {
		return nil, 0, 0, 0, err
	}
	if resp.Header["Content-Type"][0] == "sound/wav" || resp.Header["Content-Type"][0] == "audio/x-wav" {
		_, format, err := readHeader(resp.Body)
		if err != nil {
			return nil, 0, 0, 0, err
		}
		return resp.Body, format.Channels, format.SampleBytes, format.SampleRate, nil
	}
	if resp.Header["Content-Type"][0] == "audio/l16;rate=8000" {
		return resp.Body, 1, 2, 8000, nil
	}
	return nil, 0, 0, 0, errors.New("Source in unrecognized format.")
}

func failOn(e error){
	if e!=nil {panic(e)}
}
<commit_msg>comment<commit_after>package signals

import (
	"errors"
	"io"
	"net/http"
	"encoding/gob"
)
func init() {
	gob.Register(&Wave{})
}

const bufferSize = 16

// a PCM-Signal read, as required, from a URL.
// if queried for a property value for an x that is more than 32 samples lower than a previous query, will return zero.
type Wave struct{
	Shifted
	URL string
	reader io.Reader
}

func NewWave(URL string) (*Wave, error) {
	r, channels, bytes, rate, err := PCMReader(URL)
	if err!=nil {
		return nil,err
	}
	if channels != 1 {
		return nil, errors.New(URL+":Needs to be mono.")
	}
	b := make([]byte, bufferSize*bytes)
	n, err := r.Read(b)
	failOn(err)
	b=b[:n]
	switch bytes {
	case 1:
		return &Wave{Shifted{NewPCM8bit(rate, b),0},URL,r}, nil
	case 2:
		return &Wave{Shifted{NewPCM16bit(rate, b),0},URL,r}, nil
	case 3:
		return &Wave{Shifted{NewPCM24bit(rate, b),0},URL,r}, nil
	case 4:
		return &Wave{Shifted{NewPCM32bit(rate, b),0},URL,r}, nil
	case 6:
		return &Wave{Shifted{NewPCM48bit(rate, b),0},URL,r}, nil
	case 8:
		return &Wave{Shifted{NewPCM64bit(rate, b),0},URL,r}, nil
	}
	return nil, ErrWavParse{"Source bit rate not supported."}
}

func (s *Wave) property(offset x) y {
	if s.reader==nil{
		wav,err:=NewWave(s.URL)
		failOn(err)
		s.Shifted=wav.Shifted
		s.reader=wav.reader
	}
	for offset > s.MaxX() {
		// append available data onto the PCM slice.
		// also possibly shift off some data, shortening the PCM slice, retaining at least two buffer lengths.
		// semi-samples are read but not accessed by property.
		switch st:=s.Shifted.Signal.(type) {
		case PCM8bit:
			sd:=PCM8bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize+n]
			if len(sd.Data)>bufferSize*3{
				sd.Data=sd.Data[bufferSize:]
				s.Shifted.Shift+=bufferSize*st.samplePeriod
			}
			s.Shifted=Shifted{sd,s.Shifted.Shift}
		case PCM16bit:
			sd:=PCM16bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize*2)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize*2:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize*2+n]
			if len(sd.Data)>bufferSize*2*3{
				sd.Data=sd.Data[bufferSize*2:]
				s.Shifted=Shifted{sd,s.Shifted.Shift+bufferSize*st.samplePeriod}
				}else{
				s.Shifted=Shifted{sd,s.Shifted.Shift}
			}
		case PCM24bit:
			sd:=PCM24bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize*3)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize*3:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize*3+n]
			if len(sd.Data)>bufferSize*3*3{
				sd.Data=sd.Data[bufferSize*3:]
				s.Shifted=Shifted{sd,s.Shifted.Shift+bufferSize*st.samplePeriod}
				}else{
				s.Shifted=Shifted{sd,s.Shifted.Shift}
			}
		case PCM32bit:
			sd:=PCM16bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize*4)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize*4:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize*4+n]
			if len(sd.Data)>bufferSize*4*3{
				sd.Data=sd.Data[bufferSize*4:]
				s.Shifted=Shifted{sd,s.Shifted.Shift+bufferSize*st.samplePeriod}
				}else{
				s.Shifted=Shifted{sd,s.Shifted.Shift}
			}
		case PCM48bit:
			sd:=PCM48bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize*6)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize*6:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize*6+n]
			if len(sd.Data)>bufferSize*6*3{
				sd.Data=sd.Data[bufferSize*6:]
				s.Shifted=Shifted{sd,s.Shifted.Shift+bufferSize*st.samplePeriod}
				}else{
				s.Shifted=Shifted{sd,s.Shifted.Shift}
			}
		case PCM64bit:
			sd:=PCM64bit{st.PCM}
			sd.Data=append(sd.Data,make([]byte,bufferSize*8)...)
			n, err := s.reader.Read(sd.Data[len(sd.Data)-bufferSize*8:])
			failOn(err)
			sd.Data=sd.Data[:len(sd.Data)-bufferSize*8+n]
			if len(sd.Data)>bufferSize*8*3{
				sd.Data=sd.Data[bufferSize*8:]
				s.Shifted=Shifted{sd,s.Shifted.Shift+bufferSize*st.samplePeriod}
				}else{
				s.Shifted=Shifted{sd,s.Shifted.Shift}
			}
		}
	}
	return s.Shifted.property(offset)
}

//func updateShifted(s Shifted, r io.Reader, b *[]byte, blockSize int) (err error){
//	b=append(b,make([]byte,bufferSize*blockSize)...)
//	n, err := r.Read(b[len(b)-bufferSize*blockSize:])
//	failOn(err)
//	b=b[:len(b)-bufferSize*blockSize+n]
//	if len(b)>bufferSize*blockSize*3{
//		b=b[bufferSize*blockSize:]
//		s.Shift+=bufferSize*s.samplePeriod
//	}
//}

func PCMReader(source string) (io.Reader, uint16, uint16, uint32, error) {
	resp, err := http.Get(source)
	if err != nil {
		return nil, 0, 0, 0, err
	}
	if resp.Header["Content-Type"][0] == "sound/wav" || resp.Header["Content-Type"][0] == "audio/x-wav" {
		_, format, err := readHeader(resp.Body)
		if err != nil {
			return nil, 0, 0, 0, err
		}
		return resp.Body, format.Channels, format.SampleBytes, format.SampleRate, nil
	}
	if resp.Header["Content-Type"][0] == "audio/l16;rate=8000" {
		return resp.Body, 1, 2, 8000, nil
	}
	return nil, 0, 0, 0, errors.New("Source in unrecognized format.")
}

func failOn(e error){
	if e!=nil {panic(e)}
}
<|endoftext|>


<commit_before>package controllers

import (
    "crypto/sha1"
    "encoding/xml"
    "fmt"
    "github.com/astaxie/beego"
    "io/ioutil"
    "net/http"
    "sort"
    "strings"
    "time"
)

const (
    TOKEN    = "yiiliwechattoken"
    Text     = "text"
    Location = "location"
    Image    = "image"
    Link     = "link"
    Event    = "event"
    Music    = "music"
    News     = "news"
)

type msgBase struct {
    ToUserName   string
    FromUserName string
    CreateTime   time.Duration
    MsgType      string
    Content      string
}

type Request struct {
    XMLName                xml.Name `xml:"xml"`
    msgBase                         // base struct
    Location_X, Location_Y float32
    Scale                  int
    Label                  string
    PicUrl                 string
    MsgId                  int
}

type Response struct {
    XMLName xml.Name `xml:"xml"`
    msgBase
    ArticleCount int     `xml:",omitempty"`
    Articles     []*item `xml:"Articles>item,omitempty"`
    FuncFlag     int
}

type item struct {
    XMLName     xml.Name `xml:"item"`
    Title       string
    Description string
    PicUrl      string
    Url         string
}

type MainController struct {
    beego.Controller
}

func (this *MainController) Get() {
    signature := this.Input().Get("signature")
    beego.Info("signature:"+signature)
    timestamp := this.Input().Get("timestamp")
    beego.Info("timestamp:"+timestamp)
    nonce := this.Input().Get("nonce")
    beego.Info("nonce:"+nonce)
    echostr := this.Input().Get("echostr")
    beego.Info("echostr:"+echostr)
    beego.Info(Signature(timestamp, nonce))
    if Signature(timestamp, nonce) == signature {
        beego.Info("signature matched")
        this.Ctx.WriteString(echostr)
    } else {
        beego.Info("signature not matched")
        this.Ctx.WriteString("")
    }
}

func (this *MainController) Post() {
    body, err := ioutil.ReadAll(this.Ctx.Request.Body)
    if err != nil {
        beego.Error(err)
        this.Ctx.ResponseWriter.WriteHeader(500)
        return
    }
    beego.Info(string(body))
    var wreq *Request
    if wreq, err = DecodeRequest(body); err != nil {
        beego.Error(err)
        this.Ctx.ResponseWriter.WriteHeader(500)
        return
    }
    beego.Info(wreq.Content)
    wresp, err := dealwith(wreq)
    if err != nil {
        beego.Error(err)
        this.Ctx.ResponseWriter.WriteHeader(500)
        return
    }
    data, err := wresp.Encode()
    if err != nil {
        beego.Error(err)
        this.Ctx.ResponseWriter.WriteHeader(500)
        return
    }
    this.Ctx.WriteString(string(data))
    return
}

func dealwith(req *Request) (resp *Response, err error) {
    resp = NewResponse()
    resp.ToUserName = req.FromUserName
    resp.FromUserName = req.ToUserName
    resp.MsgType = Text
    beego.Info(req.MsgType)
    beego.Info(req.Content)
    if req.MsgType == Text {
        userInputText := strings.Trim(strings.ToLower(req.Content), " ")
        if userInputText == "help" || userInputText == `帮助` {
            resp.Content = `您好，感谢关注衣丽社区微信公众号i-yiili，希望我们能为您的生活提供一点帮助。
            我们会通过微信公众号向您不定期地推送一些涉及美容美发化妆、穿着搭配、运动健康、饮食营养、情绪修养等跟女性生活息息相关的文章。
            同时借助微信公众号强大的可定制性，我们也提供了一系列丰富的功能，并且将不断增加新的实用的功能。
            输入“文章+日期”或“wz+日期”如（文章20141022 或 wz20141022），显示该天衣丽社区微信公众号发布的文章链接。
            输入“微店”或“wd”，显示衣丽社区关联的微店地址。
            输入“女装”或“nz”，显示衣丽社区主持出售的女装商品信息。
            输入“面膜”或“mm”，显示衣丽社区主持出售的面膜商品信息。
            输入商品id（如：310148677），显示衣丽社区主持出售的对应商品信息。
            输入任意关键字，显示包含该关键字的衣丽社区主持出售的商品信息。
            其他更多功能，敬请期待。`
            return resp, nil
        }
        strs := strings.Split(req.Content, ".")
        var resurl string
        var a item
        if len(strs) == 1 {
            resurl = "https://raw.github.com/astaxie/gopkg/master/" + strings.Trim(strings.ToLower(strs[0]), " ") + "/README.md"
            a.Url = "https://github.com/astaxie/gopkg/tree/master/" + strings.Trim(strings.ToLower(strs[0]), " ") + "/README.md"
        } else {
            var other []string
            for k, v := range strs {
                if k < (len(strs) - 1) {
                    other = append(other, strings.Trim(strings.ToLower(v), " "))
                } else {
                    other = append(other, strings.Trim(strings.Title(v), " "))
                }
            }
            resurl = "https://raw.github.com/astaxie/gopkg/master/" + strings.Join(other, "/") + ".md"
            a.Url = "https://github.com/astaxie/gopkg/tree/master/" + strings.Join(other, "/") + ".md"
        }
        beego.Info(resurl)
        rsp, err := http.Get(resurl)
        if err != nil {
            resp.Content = "不存在该包内容"
            return nil, err
        }
        defer rsp.Body.Close()
        if rsp.StatusCode == 404 {
            resp.Content = "找不到你要查询的包:" + req.Content
            return resp, nil
        }
        resp.MsgType = News
        resp.ArticleCount = 1
        body, err := ioutil.ReadAll(rsp.Body)
        beego.Info(string(body))
        a.Description = string(body)
        a.Title = req.Content
        a.PicUrl = "http://bbs.gocn.im/static/image/common/logo.png"
        resp.Articles = append(resp.Articles, &a)
        resp.FuncFlag = 1
    } else {
        resp.Content = "暂时还不支持其他的类型"
    }
    return resp, nil
}

func Signature(timestamp, nonce string) string {
    strs := sort.StringSlice{TOKEN, timestamp, nonce}
    sort.Strings(strs)
    str := ""
    for _, s := range strs {
        str += s
    }
    h := sha1.New()
    h.Write([]byte(str))
    return fmt.Sprintf("%x", h.Sum(nil))
}

func DecodeRequest(data []byte) (req *Request, err error) {
    req = &Request{}
    if err = xml.Unmarshal(data, req); err != nil {
        return
    }
    req.CreateTime *= time.Second
    return
}

func NewResponse() (resp *Response) {
    resp = &Response{}
    resp.CreateTime = time.Duration(time.Now().Unix())
    return
}

func (resp Response) Encode() (data []byte, err error) {
    resp.CreateTime = time.Second
    data, err = xml.Marshal(resp)
    return
}
<commit_msg>(+)add wd command handler<commit_after>package controllers

import (
	"crypto/sha1"
	"encoding/xml"
	"fmt"
	"github.com/astaxie/beego"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"
)

const (
	TOKEN       = "yiiliwechattoken"
	Text        = "text"
	Location    = "location"
	Image       = "image"
	Link        = "link"
	Event       = "event"
	Music       = "music"
	News        = "news"
	HelpContent = `您好，感谢关注衣丽社区微信公众号i-yiili，希望我们能为您的生活提供一点帮助。
            我们会通过微信公众号向您不定期地推送一些涉及美容美发化妆、穿着搭配、运动健康、饮食营养、情绪修养等跟女性生活息息相关的文章。
            同时借助微信公众号强大的可定制性，我们也提供了一系列丰富的功能，并且将不断增加新的实用的功能。
            输入“文章+日期”或“wz+日期”如（文章20141022 或 wz20141022），显示该天衣丽社区微信公众号发布的文章链接。
            输入“微店”或“wd”，显示衣丽社区关联的微店地址。
            输入“女装”或“nz”，显示衣丽社区主持出售的女装商品信息。
            输入“面膜”或“mm”，显示衣丽社区主持出售的面膜商品信息。
            输入商品id（如：310148677），显示衣丽社区主持出售的对应商品信息。
            输入任意关键字，显示包含该关键字的衣丽社区主持出售的商品信息。
            其他更多功能，敬请期待。`
)

type msgBase struct {
	ToUserName   string
	FromUserName string
	CreateTime   time.Duration
	MsgType      string
	Content      string
}

type Request struct {
	XMLName                xml.Name `xml:"xml"`
	msgBase                         // base struct
	Location_X, Location_Y float32
	Scale                  int
	Label                  string
	PicUrl                 string
	MsgId                  int
}

type Response struct {
	XMLName xml.Name `xml:"xml"`
	msgBase
	ArticleCount int     `xml:",omitempty"`
	Articles     []*item `xml:"Articles>item,omitempty"`
	FuncFlag     int
}

type item struct {
	XMLName     xml.Name `xml:"item"`
	Title       string
	Description string
	PicUrl      string
	Url         string
}

type MainController struct {
	beego.Controller
}

func (this *MainController) Get() {
	signature := this.Input().Get("signature")
	beego.Info("signature:" + signature)
	timestamp := this.Input().Get("timestamp")
	beego.Info("timestamp:" + timestamp)
	nonce := this.Input().Get("nonce")
	beego.Info("nonce:" + nonce)
	echostr := this.Input().Get("echostr")
	beego.Info("echostr:" + echostr)
	beego.Info(Signature(timestamp, nonce))
	if Signature(timestamp, nonce) == signature {
		beego.Info("signature matched")
		this.Ctx.WriteString(echostr)
	} else {
		beego.Info("signature not matched")
		this.Ctx.WriteString("")
	}
}

func (this *MainController) Post() {
	body, err := ioutil.ReadAll(this.Ctx.Request.Body)
	if err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	beego.Info(string(body))
	var wreq *Request
	if wreq, err = DecodeRequest(body); err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	beego.Info(wreq.Content)
	wresp, err := dealwith(wreq)
	if err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	data, err := wresp.Encode()
	if err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	this.Ctx.WriteString(string(data))
	return
}

func dealwith(req *Request) (resp *Response, err error) {
	resp = NewResponse()
	resp.ToUserName = req.FromUserName
	resp.FromUserName = req.ToUserName
	resp.MsgType = Text
	beego.Info(req.MsgType)
	beego.Info(req.Content)
	if req.MsgType == Text {
		userInputText := strings.Trim(strings.ToLower(req.Content), " ")
		if userInputText == "help" || userInputText == `帮助` {
			resp.Content = HelpContent
			return resp, nil
		}
		var a item
		if userInputText == "wd" || userInputText == `微店` {
			resp.MsgType = News
			resp.ArticleCount = 1
			a.Description = `女装专卖，经典时尚大方，赶快来看看吧:)`
			a.Title = `凯莉小姐的梦想女装店`
			a.PicUrl = "http://wd.geilicdn.com/vshop215091300-1413902752.jpg"
			a.Url = "http://shopwd.yii.li"
			resp.Articles = append(resp.Articles, &a)
			resp.FuncFlag = 1
			return resp, nil
		}
		strs := strings.Split(req.Content, ".")
		var resurl string
		if len(strs) == 1 {
			resurl = "https://raw.github.com/astaxie/gopkg/master/" + strings.Trim(strings.ToLower(strs[0]), " ") + "/README.md"
			a.Url = "https://github.com/astaxie/gopkg/tree/master/" + strings.Trim(strings.ToLower(strs[0]), " ") + "/README.md"
		} else {
			var other []string
			for k, v := range strs {
				if k < (len(strs) - 1) {
					other = append(other, strings.Trim(strings.ToLower(v), " "))
				} else {
					other = append(other, strings.Trim(strings.Title(v), " "))
				}
			}
			resurl = "https://raw.github.com/astaxie/gopkg/master/" + strings.Join(other, "/") + ".md"
			a.Url = "https://github.com/astaxie/gopkg/tree/master/" + strings.Join(other, "/") + ".md"
		}
		beego.Info(resurl)
		rsp, err := http.Get(resurl)
		if err != nil {
			resp.Content = "不存在该包内容"
			return nil, err
		}
		defer rsp.Body.Close()
		if rsp.StatusCode == 404 {
			resp.Content = "找不到你要查询的包:" + req.Content
			return resp, nil
		}
		resp.MsgType = News
		resp.ArticleCount = 1
		body, err := ioutil.ReadAll(rsp.Body)
		beego.Info(string(body))
		a.Description = string(body)
		a.Title = req.Content
		a.PicUrl = "http://bbs.gocn.im/static/image/common/logo.png"
		resp.Articles = append(resp.Articles, &a)
		resp.FuncFlag = 1
	} else {
		resp.Content = "暂时还不支持其他的类型"
	}
	return resp, nil
}

func Signature(timestamp, nonce string) string {
	strs := sort.StringSlice{TOKEN, timestamp, nonce}
	sort.Strings(strs)
	str := ""
	for _, s := range strs {
		str += s
	}
	h := sha1.New()
	h.Write([]byte(str))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func DecodeRequest(data []byte) (req *Request, err error) {
	req = &Request{}
	if err = xml.Unmarshal(data, req); err != nil {
		return
	}
	req.CreateTime *= time.Second
	return
}

func NewResponse() (resp *Response) {
	resp = &Response{}
	resp.CreateTime = time.Duration(time.Now().Unix())
	return
}

func (resp Response) Encode() (data []byte, err error) {
	resp.CreateTime = time.Second
	data, err = xml.Marshal(resp)
	return
}
<|endoftext|>


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

// This file implements Selections.

package types

import (
	"bytes"
	"fmt"
)

// SelectionKind describes the kind of a selector expression x.f.
type SelectionKind int

const (
	FieldVal   SelectionKind = iota // x.f is a struct field selector
	MethodVal                       // x.f is a method selector
	MethodExpr                      // x.f is a method expression
	PackageObj                      // x.f is a qualified identifier
)

// A Selection describes a selector expression x.f.
// For the declarations:
//
//	type T struct{ x int; E }
//	type E struct{}
//	func (e E) m() {}
//	var p *T
//
// the following relations exist:
//
//	Selector    Kind          Recv    Obj    Type               Index     Indirect
//
//	p.x         FieldVal      T       x      int                {0}       true
//	p.m         MethodVal     *T      m      func (e *T) m()    {1, 0}    true
//	T.m         MethodExpr    T       m      func m(_ T)        {1, 0}    false
//	math.Pi     PackageObj    nil     Pi     untyped numeric    nil       false
//
type Selection struct {
	kind     SelectionKind
	recv     Type   // type of x, nil if kind == PackageObj
	obj      Object // object denoted by x.f
	index    []int  // path from x to x.f, nil if kind == PackageObj
	indirect bool   // set if there was any pointer indirection on the path, false if kind == PackageObj
}

// Kind returns the selection kind.
func (s *Selection) Kind() SelectionKind { return s.kind }

// Recv returns the type of x in x.f.
// The result is nil if x.f is a qualified identifier (PackageObj).
func (s *Selection) Recv() Type { return s.recv }

// Obj returns the object denoted by x.f.
// The following object types may appear:
//
//	Kind          Object
//
//	FieldVal      *Var                          field
//	MethodVal     *Func                         method
//	MethodExpr    *Func                         method
//	PackageObj    *Const, *Type, *Var, *Func    imported const, type, var, or func
//
func (s *Selection) Obj() Object { return s.obj }

// Type returns the type of x.f, which may be different from the type of f.
// See Selection for more information.
func (s *Selection) Type() Type {
	switch s.kind {
	case MethodVal:
		// The type of x.f is a method with its receiver type set
		// to the type of x.
		sig := *s.obj.(*Func).typ.(*Signature)
		recv := *sig.recv
		recv.typ = s.recv
		sig.recv = &recv
		return &sig

	case MethodExpr:
		// The type of x.f is a function (without receiver)
		// and an additional first argument with the same type as x.
		// TODO(gri) Similar code is already in call.go - factor!
		sig := *s.obj.(*Func).typ.(*Signature)
		arg0 := *sig.recv
		arg0.typ = s.recv
		var params []*Var
		if sig.params != nil {
			params = sig.params.vars
		}
		sig.params = NewTuple(append([]*Var{&arg0}, params...)...)
		return &sig
	}

	// In all other cases, the type of x.f is the type of x.
	return s.obj.Type()
}

// Index describes the path from x to f in x.f.
// The result is nil if x.f is a qualified identifier (PackageObj).
//
// The last index entry is the field or method index of the type declaring f;
// either:
//
//	1) the list of declared methods of a named type; or
//	2) the list of methods of an interface type; or
//	3) the list of fields of a struct type.
//
// The earlier index entries are the indices of the embedded fields implicitly
// traversed to get from (the type of) x to f, starting at embedding depth 0.
func (s *Selection) Index() []int { return s.index }

// Indirect reports whether any pointer indirection was required to get from
// x to f in x.f.
// The result is false if x.f is a qualified identifier (PackageObj).
func (s *Selection) Indirect() bool { return s.indirect }

func (s *Selection) String() string { return SelectionString(nil, s) }

// SelectionString returns the string form of s.
// Type names are printed package-qualified
// only if they do not belong to this package.
//
func SelectionString(this *Package, s *Selection) string {
	var k string
	switch s.kind {
	case FieldVal:
		k = "field "
	case MethodVal:
		k = "method "
	case MethodExpr:
		k = "method expr "
	case PackageObj:
		return fmt.Sprintf("qualified ident %s", s.obj)
	default:
		unreachable()
	}
	var buf bytes.Buffer
	buf.WriteString(k)
	buf.WriteByte('(')
	WriteType(&buf, this, s.Recv())
	fmt.Fprintf(&buf, ") %s", s.obj.Name())
	WriteSignature(&buf, this, s.Type().(*Signature))
	return buf.String()
}
<commit_msg>go.tools/go/types: fix incorrect receiver in (*Selection).Type().<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements Selections.

package types

import (
	"bytes"
	"fmt"
)

// SelectionKind describes the kind of a selector expression x.f.
type SelectionKind int

const (
	FieldVal   SelectionKind = iota // x.f is a struct field selector
	MethodVal                       // x.f is a method selector
	MethodExpr                      // x.f is a method expression
	PackageObj                      // x.f is a qualified identifier
)

// A Selection describes a selector expression x.f.
// For the declarations:
//
//	type T struct{ x int; E }
//	type E struct{}
//	func (e E) m() {}
//	var p *T
//
// the following relations exist:
//
//	Selector    Kind          Recv    Obj    Type               Index     Indirect
//
//	p.x         FieldVal      T       x      int                {0}       true
//	p.m         MethodVal     *T      m      func (e *T) m()    {1, 0}    true
//	T.m         MethodExpr    T       m      func m(_ T)        {1, 0}    false
//	math.Pi     PackageObj    nil     Pi     untyped numeric    nil       false
//
type Selection struct {
	kind     SelectionKind
	recv     Type   // type of x, nil if kind == PackageObj
	obj      Object // object denoted by x.f
	index    []int  // path from x to x.f, nil if kind == PackageObj
	indirect bool   // set if there was any pointer indirection on the path, false if kind == PackageObj
}

// Kind returns the selection kind.
func (s *Selection) Kind() SelectionKind { return s.kind }

// Recv returns the type of x in x.f.
// The result is nil if x.f is a qualified identifier (PackageObj).
func (s *Selection) Recv() Type { return s.recv }

// Obj returns the object denoted by x.f.
// The following object types may appear:
//
//	Kind          Object
//
//	FieldVal      *Var                          field
//	MethodVal     *Func                         method
//	MethodExpr    *Func                         method
//	PackageObj    *Const, *Type, *Var, *Func    imported const, type, var, or func
//
func (s *Selection) Obj() Object { return s.obj }

// Type returns the type of x.f, which may be different from the type of f.
// See Selection for more information.
func (s *Selection) Type() Type {
	switch s.kind {
	case MethodVal:
		// The type of x.f is a method with its receiver type set
		// to the type of x.
		sig := *s.obj.(*Func).typ.(*Signature)
		recv := *sig.recv
		recv.typ = s.recv
		sig.recv = &recv
		return &sig

	case MethodExpr:
		// The type of x.f is a function (without receiver)
		// and an additional first argument with the same type as x.
		// TODO(gri) Similar code is already in call.go - factor!
		sig := *s.obj.(*Func).typ.(*Signature)
		arg0 := *sig.recv
		sig.recv = nil
		arg0.typ = s.recv
		var params []*Var
		if sig.params != nil {
			params = sig.params.vars
		}
		sig.params = NewTuple(append([]*Var{&arg0}, params...)...)
		return &sig
	}

	// In all other cases, the type of x.f is the type of x.
	return s.obj.Type()
}

// Index describes the path from x to f in x.f.
// The result is nil if x.f is a qualified identifier (PackageObj).
//
// The last index entry is the field or method index of the type declaring f;
// either:
//
//	1) the list of declared methods of a named type; or
//	2) the list of methods of an interface type; or
//	3) the list of fields of a struct type.
//
// The earlier index entries are the indices of the embedded fields implicitly
// traversed to get from (the type of) x to f, starting at embedding depth 0.
func (s *Selection) Index() []int { return s.index }

// Indirect reports whether any pointer indirection was required to get from
// x to f in x.f.
// The result is false if x.f is a qualified identifier (PackageObj).
func (s *Selection) Indirect() bool { return s.indirect }

func (s *Selection) String() string { return SelectionString(nil, s) }

// SelectionString returns the string form of s.
// Type names are printed package-qualified
// only if they do not belong to this package.
//
func SelectionString(this *Package, s *Selection) string {
	var k string
	switch s.kind {
	case FieldVal:
		k = "field "
	case MethodVal:
		k = "method "
	case MethodExpr:
		k = "method expr "
	case PackageObj:
		return fmt.Sprintf("qualified ident %s", s.obj)
	default:
		unreachable()
	}
	var buf bytes.Buffer
	buf.WriteString(k)
	buf.WriteByte('(')
	WriteType(&buf, this, s.Recv())
	fmt.Fprintf(&buf, ") %s", s.obj.Name())
	WriteSignature(&buf, this, s.Type().(*Signature))
	return buf.String()
}
<|endoftext|>


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

package loader

import (
	"bufio"
	"io"
	"math/rand"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/dgraph-io/dgraph/posting"
	"github.com/dgraph-io/dgraph/rdf"
	"github.com/dgraph-io/dgraph/x"
	"github.com/dgryski/go-farm"
)

var glog = x.Log("loader")

type counters struct {
	read      uint64
	parsed    uint64
	processed uint64
	ignored   uint64
}

type state struct {
	input chan string
	cnq   chan rdf.NQuad
	ctr   *counters
	mod   uint64
	numInstance uint64
}

func (s *state) printCounters(ticker *time.Ticker) {
	var prev uint64
	for _ = range ticker.C {
		processed := atomic.LoadUint64(&s.ctr.processed)
		if prev == processed {
			continue
		}
		prev = processed
		parsed := atomic.LoadUint64(&s.ctr.parsed)
		ignored := atomic.LoadUint64(&s.ctr.ignored)
		pending := parsed - ignored - processed
		glog.WithFields(logrus.Fields{
			"read":      atomic.LoadUint64(&s.ctr.read),
			"processed": processed,
			"parsed":    parsed,
			"ignored":   ignored,
			"pending":   pending,
			"len_cnq":   len(s.cnq),
		}).Info("Counters")
	}
}

func (s *state) readLines(r io.Reader) {
	var buf []string
	scanner := bufio.NewScanner(r)
	// Randomize lines to avoid contention on same subject.
	for i := 0; i < 1000; i++ {
		if scanner.Scan() {
			buf = append(buf, scanner.Text())
		} else {
			break
		}
	}
	ln := len(buf)
	for scanner.Scan() {
		k := rand.Intn(ln)
		s.input <- buf[k]
		buf[k] = scanner.Text()
		atomic.AddUint64(&s.ctr.read, 1)
	}
	if err := scanner.Err(); err != nil {
		glog.WithError(err).Fatal("While reading file.")
	}
	for i := 0; i < len(buf); i++ {
		s.input <- buf[i]
	}
	close(s.input)
}

func (s *state) parseStream(done chan error) {
	for line := range s.input {
		line = strings.Trim(line, " \t")
		if len(line) == 0 {
			glog.Info("Empty line.")
			continue
		}

		glog.Debugf("Got line: %q", line)
		nq, err := rdf.Parse(line)
		if err != nil {
			glog.WithError(err).Errorf("While parsing: %q", line)
			done <- err
			return
		}
		s.cnq <- nq
		atomic.AddUint64(&s.ctr.parsed, 1)
	}
	done <- nil
}

func (s *state) handleNQuads(wg *sync.WaitGroup) {
	for nq := range s.cnq {
		if farm.Fingerprint64([]byte(nq.Subject))%s.mod != 0 {
			// Ignore due to mod sampling.
			atomic.AddUint64(&s.ctr.ignored, 1)
			continue
		}

		edge, err := nq.ToEdge(s.mod, s.numInstance)
		for err != nil {
			// Just put in a retry loop to tackle temporary errors.
			if err == posting.E_TMP_ERROR {
				time.Sleep(time.Microsecond)

			} else {
				glog.WithError(err).WithField("nq", nq).
					Error("While converting to edge")
				return
			}
			edge, err = nq.ToEdge(s.mod, s.numInstance)
		}

		key := posting.Key(edge.Entity, edge.Attribute)
		plist := posting.GetOrCreate(key)
		plist.AddMutation(edge, posting.Set)
		atomic.AddUint64(&s.ctr.processed, 1)
	}
	wg.Done()
}

func (s *state) handleNQuadsWhileAssign(wg *sync.WaitGroup) {
	for nq := range s.cnq {
		if farm.Fingerprint64([]byte(nq.Subject))%s.numInstance != s.mod {
			// This instance shouldnt assign UID to this string
			atomic.AddUint64(&s.ctr.ignored, 1)
		} else {
			_, err := rdf.GetUid(nq.Subject, s.mod, s.numInstance)
			for err != nil {
				// Just put in a retry loop to tackle temporary errors.
				if err == posting.E_TMP_ERROR {
					time.Sleep(time.Microsecond)
				} else {
					glog.WithError(err).WithField("nq.Subject", nq.Subject).
						Error("While getting UID")
					return
				}
				_, err = rdf.GetUid(nq.Subject, s.mod, s.numInstance)
			}
		}

		if len(nq.ObjectId) == 0 || farm.Fingerprint64([]byte(nq.ObjectId))%s.numInstance != s.mod {
                        // This instance shouldnt or cant assign UID to this string
                        atomic.AddUint64(&s.ctr.ignored, 1)
                } else {
                        _, err := rdf.GetUid(nq.ObjectId, s.mod, s.numInstance)
                        for err != nil {
                                // Just put in a retry loop to tackle temporary errors.
                                if err == posting.E_TMP_ERROR {
                                        time.Sleep(time.Microsecond)
                                } else {
                                        glog.WithError(err).WithField("nq.ObjectId", nq.ObjectId).
                                                Error("While getting UID")
                                        return
                                }
                                _, err = rdf.GetUid(nq.ObjectId, s.mod, s.numInstance)
                        }
                }
	}
	wg.Done()
}

// Blocking function.
func HandleRdfReader(reader io.Reader, mod uint64) (uint64, error) {
	s := new(state)
	s.ctr = new(counters)
	ticker := time.NewTicker(time.Second)
	go s.printCounters(ticker)

	// Producer: Start buffering input to channel.
	s.mod = mod
	s.input = make(chan string, 10000)
	go s.readLines(reader)

	s.cnq = make(chan rdf.NQuad, 10000)
	numr := runtime.GOMAXPROCS(-1)
	done := make(chan error, numr)
	for i := 0; i < numr; i++ {
		go s.parseStream(done) // Input --> NQuads
	}

	wg := new(sync.WaitGroup)
	for i := 0; i < 3000; i++ {
		wg.Add(1)
		go s.handleNQuads(wg) // NQuads --> Posting list [slow].
	}

	// Block until all parseStream goroutines are finished.
	for i := 0; i < numr; i++ {
		if err := <-done; err != nil {
			glog.WithError(err).Fatal("While reading input.")
		}
	}

	close(s.cnq)
	// Okay, we've stopped input to cnq, and closed it.
	// Now wait for handleNQuads to finish.
	wg.Wait()

	ticker.Stop()
	return atomic.LoadUint64(&s.ctr.processed), nil
}

// Blocking function.
func HandleRdfReaderWhileAssign(reader io.Reader, mod uint64, numInstance uint64) (uint64, error) {
	s := new(state)
	s.ctr = new(counters)
	ticker := time.NewTicker(time.Second)
	go s.printCounters(ticker)

	// Producer: Start buffering input to channel.
	s.mod = mod
	s.numInstance = numInstance
	s.input = make(chan string, 10000)
	go s.readLines(reader)

	s.cnq = make(chan rdf.NQuad, 10000)
	numr := runtime.GOMAXPROCS(-1)
	done := make(chan error, numr)
	for i := 0; i < numr; i++ {
		go s.parseStream(done) // Input --> NQuads
	}

	wg := new(sync.WaitGroup)
	for i := 0; i < 3000; i++ {
		wg.Add(1)
		go s.handleNQuadsWhileAssign(wg) //Different compared to HandleRdfReader
	}

	// Block until all parseStream goroutines are finished.
	for i := 0; i < numr; i++ {
		if err := <-done; err != nil {
			glog.WithError(err).Fatal("While reading input.")
		}
	}

	close(s.cnq)
	// Okay, we've stopped input to cnq, and closed it.
	// Now wait for handleNQuads to finish.
	wg.Wait()

	ticker.Stop()
	return atomic.LoadUint64(&s.ctr.processed), nil
}

<commit_msg>Removed mod sampling<commit_after>/*
 * Copyright 2015 Manish R Jain <manishrjain@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 		http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package loader

import (
	"bufio"
	"io"
	"math/rand"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/dgraph-io/dgraph/posting"
	"github.com/dgraph-io/dgraph/rdf"
	"github.com/dgraph-io/dgraph/x"
	"github.com/dgryski/go-farm"
)

var glog = x.Log("loader")

type counters struct {
	read      uint64
	parsed    uint64
	processed uint64
	ignored   uint64
}

type state struct {
	input chan string
	cnq   chan rdf.NQuad
	ctr   *counters
	mod   uint64
	numInstance uint64
}

func (s *state) printCounters(ticker *time.Ticker) {
	var prev uint64
	for _ = range ticker.C {
		processed := atomic.LoadUint64(&s.ctr.processed)
		if prev == processed {
			continue
		}
		prev = processed
		parsed := atomic.LoadUint64(&s.ctr.parsed)
		ignored := atomic.LoadUint64(&s.ctr.ignored)
		pending := parsed - ignored - processed
		glog.WithFields(logrus.Fields{
			"read":      atomic.LoadUint64(&s.ctr.read),
			"processed": processed,
			"parsed":    parsed,
			"ignored":   ignored,
			"pending":   pending,
			"len_cnq":   len(s.cnq),
		}).Info("Counters")
	}
}

func (s *state) readLines(r io.Reader) {
	var buf []string
	scanner := bufio.NewScanner(r)
	// Randomize lines to avoid contention on same subject.
	for i := 0; i < 1000; i++ {
		if scanner.Scan() {
			buf = append(buf, scanner.Text())
		} else {
			break
		}
	}
	ln := len(buf)
	for scanner.Scan() {
		k := rand.Intn(ln)
		s.input <- buf[k]
		buf[k] = scanner.Text()
		atomic.AddUint64(&s.ctr.read, 1)
	}
	if err := scanner.Err(); err != nil {
		glog.WithError(err).Fatal("While reading file.")
	}
	for i := 0; i < len(buf); i++ {
		s.input <- buf[i]
	}
	close(s.input)
}

func (s *state) parseStream(done chan error) {
	for line := range s.input {
		line = strings.Trim(line, " \t")
		if len(line) == 0 {
			glog.Info("Empty line.")
			continue
		}

		glog.Debugf("Got line: %q", line)
		nq, err := rdf.Parse(line)
		if err != nil {
			glog.WithError(err).Errorf("While parsing: %q", line)
			done <- err
			return
		}
		s.cnq <- nq
		atomic.AddUint64(&s.ctr.parsed, 1)
	}
	done <- nil
}

func (s *state) handleNQuads(wg *sync.WaitGroup) {
	for nq := range s.cnq {
		edge, err := nq.ToEdge(s.mod, s.numInstance)
		for err != nil {
			// Just put in a retry loop to tackle temporary errors.
			if err == posting.E_TMP_ERROR {
				time.Sleep(time.Microsecond)

			} else {
				glog.WithError(err).WithField("nq", nq).
					Error("While converting to edge")
				return
			}
			edge, err = nq.ToEdge(s.mod, s.numInstance)
		}

		key := posting.Key(edge.Entity, edge.Attribute)
		plist := posting.GetOrCreate(key)
		plist.AddMutation(edge, posting.Set)
		atomic.AddUint64(&s.ctr.processed, 1)
	}
	wg.Done()
}

func (s *state) handleNQuadsWhileAssign(wg *sync.WaitGroup) {
	for nq := range s.cnq {
		if farm.Fingerprint64([]byte(nq.Subject))%s.numInstance != s.mod {
			// This instance shouldnt assign UID to this string
			atomic.AddUint64(&s.ctr.ignored, 1)
		} else {
			_, err := rdf.GetUid(nq.Subject, s.mod, s.numInstance)
			for err != nil {
				// Just put in a retry loop to tackle temporary errors.
				if err == posting.E_TMP_ERROR {
					time.Sleep(time.Microsecond)
					glog.WithError(err).WithField("nq.Subject", nq.Subject).
                                                Error("Temporary error")
				} else {
					glog.WithError(err).WithField("nq.Subject", nq.Subject).
						Error("While getting UID")
					return
				}
				_, err = rdf.GetUid(nq.Subject, s.mod, s.numInstance)
			}
		}

		if len(nq.ObjectId) == 0 || farm.Fingerprint64([]byte(nq.ObjectId))%s.numInstance != s.mod {
                        // This instance shouldnt or cant assign UID to this string
                        atomic.AddUint64(&s.ctr.ignored, 1)
                } else {
                        _, err := rdf.GetUid(nq.ObjectId, s.mod, s.numInstance)
                        for err != nil {
                                // Just put in a retry loop to tackle temporary errors.
                                if err == posting.E_TMP_ERROR {
                                        time.Sleep(time.Microsecond)
                			glog.WithError(err).WithField("nq.Subject", nq.Subject).
                                                Error("Temporary error")
		               } else {
                                        glog.WithError(err).WithField("nq.ObjectId", nq.ObjectId).
                                                Error("While getting UID")
                                        return
                                }
                                _, err = rdf.GetUid(nq.ObjectId, s.mod, s.numInstance)
                        }
                }
	}
	wg.Done()
}

// Blocking function.
func HandleRdfReader(reader io.Reader, mod uint64) (uint64, error) {
	s := new(state)
	s.ctr = new(counters)
	ticker := time.NewTicker(time.Second)
	go s.printCounters(ticker)

	// Producer: Start buffering input to channel.
	s.mod = mod
	s.input = make(chan string, 10000)
	go s.readLines(reader)

	s.cnq = make(chan rdf.NQuad, 10000)
	numr := runtime.GOMAXPROCS(-1)
	done := make(chan error, numr)
	for i := 0; i < numr; i++ {
		go s.parseStream(done) // Input --> NQuads
	}

	wg := new(sync.WaitGroup)
	for i := 0; i < 3000; i++ {
		wg.Add(1)
		go s.handleNQuads(wg) // NQuads --> Posting list [slow].
	}

	// Block until all parseStream goroutines are finished.
	for i := 0; i < numr; i++ {
		if err := <-done; err != nil {
			glog.WithError(err).Fatal("While reading input.")
		}
	}

	close(s.cnq)
	// Okay, we've stopped input to cnq, and closed it.
	// Now wait for handleNQuads to finish.
	wg.Wait()

	ticker.Stop()
	return atomic.LoadUint64(&s.ctr.processed), nil
}

// Blocking function.
func HandleRdfReaderWhileAssign(reader io.Reader, mod uint64, numInstance uint64) (uint64, error) {
	s := new(state)
	s.ctr = new(counters)
	ticker := time.NewTicker(time.Second)
	go s.printCounters(ticker)

	// Producer: Start buffering input to channel.
	s.mod = mod
	s.numInstance = numInstance
	s.input = make(chan string, 10000)
	go s.readLines(reader)

	s.cnq = make(chan rdf.NQuad, 10000)
	numr := runtime.GOMAXPROCS(-1)
	done := make(chan error, numr)
	for i := 0; i < numr; i++ {
		go s.parseStream(done) // Input --> NQuads
	}

	wg := new(sync.WaitGroup)
	for i := 0; i < 3000; i++ {
		wg.Add(1)
		go s.handleNQuadsWhileAssign(wg) //Different compared to HandleRdfReader
	}

	// Block until all parseStream goroutines are finished.
	for i := 0; i < numr; i++ {
		if err := <-done; err != nil {
			glog.WithError(err).Fatal("While reading input.")
		}
	}

	close(s.cnq)
	// Okay, we've stopped input to cnq, and closed it.
	// Now wait for handleNQuads to finish.
	wg.Wait()

	ticker.Stop()
	return atomic.LoadUint64(&s.ctr.processed), nil
}

<|endoftext|>


<commit_before>package golfilesystem

import (
	"fmt"
	"io"
	"log"
	"os"
	"path"
)

/*
MkDir to make dir if not there already.
*/
func MkDir(dirpath string) error {
	if PathExists(dirpath) {
		return nil
	}

	err := os.MkdirAll(dirpath, 0755)
	if err != nil {
		log.Println("Error creating directory")
		log.Println(err)
		return err
	}

	return nil
}

/*
CopyFile from src to dst
*/
func CopyFile(src, dst string) error {
	sfi, err := os.Stat(src)
	if err != nil {
		return err
	}
	if !sfi.Mode().IsRegular() {
		// cannot copy non-regular files (e.g., directories,
		// symlinks, devices, etc.)
		return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
	}
	dfi, err := os.Stat(dst)
	if err != nil {
		if !os.IsNotExist(err) {
			return err
		}
	} else {
		if !(dfi.Mode().IsRegular()) {
			return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
		}
		if os.SameFile(sfi, dfi) {
			return nil
		}
	}
	if err = os.Link(src, dst); err == nil {
		return nil
	}

	if err = MkDir(path.Dir(dst)); err != nil {
		return err
	}
	err = copyFileContents(src, dst)
	return err
}

/*
copyFileContents copies the contents of the file named src to the file named
by dst. The file will be created if it does not already exist. If the
destination file exists, all it's contents will be replaced by the contents
of the source file.
*/
func copyFileContents(src, dst string) (err error) {
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()
	out, err := os.Create(dst)
	if err != nil {
		return
	}
	defer func() {
		cerr := out.Close()
		if err == nil {
			err = cerr
		}
	}()
	if _, err = io.Copy(out, in); err != nil {
		return
	}
	err = out.Sync()
	return
}
<commit_msg>[golfilesystem] made copy over FileMode to destination<commit_after>package golfilesystem

import (
	"fmt"
	"io"
	"log"
	"os"
	"path"
)

/*
MkDir to make dir if not there already.
*/
func MkDir(dirpath string) error {
	if PathExists(dirpath) {
		return nil
	}

	err := os.MkdirAll(dirpath, 0755)
	if err != nil {
		log.Println("Error creating directory")
		log.Println(err)
		return err
	}

	return nil
}

/*
CopyFile from src to dst
*/
func CopyFile(src, dst string) error {
	sfi, err := os.Stat(src)
	if err != nil {
		return err
	}
	if !sfi.Mode().IsRegular() {
		// cannot copy non-regular files (e.g., directories,
		// symlinks, devices, etc.)
		return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
	}
	dfi, err := os.Stat(dst)
	if err != nil {
		if !os.IsNotExist(err) {
			return err
		}
	} else {
		if !(dfi.Mode().IsRegular()) {
			return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
		}
		if os.SameFile(sfi, dfi) {
			return nil
		}
	}
	if err = os.Link(src, dst); err == nil {
		return nil
	}

	if err = MkDir(path.Dir(dst)); err != nil {
		return err
	}
	err = copyFileContents(src, dst, sfi.Mode())
	return err
}

/*
copyFileContents copies the contents of the file named src to the file named
by dst. The file will be created if it does not already exist. If the
destination file exists, all it's contents will be replaced by the contents
of the source file.
*/
func copyFileContents(src string, dst string, srcMode os.FileMode) (err error) {
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()
	out, err := os.Create(dst)
	out.Chmod(srcMode)
	if err != nil {
		return
	}
	defer func() {
		cerr := out.Close()
		if err == nil {
			err = cerr
		}
	}()
	if _, err = io.Copy(out, in); err != nil {
		return
	}
	err = out.Sync()
	return
}
<|endoftext|>