<commit_before>package video

var scan = [2][8][8]int{
	{
		{0, 1, 5, 6, 14, 15, 27, 28},
		{2, 4, 7, 13, 16, 26, 29, 42},
		{3, 8, 12, 17, 25, 30, 41, 43},
		{9, 11, 18, 24, 31, 40, 44, 53},
		{10, 19, 23, 32, 39, 45, 52, 54},
		{20, 22, 33, 38, 46, 51, 55, 60},
		{21, 34, 37, 47, 50, 56, 59, 61},
		{35, 36, 48, 49, 57, 58, 62, 63},
	},
	{
		{0, 4, 6, 20, 22, 36, 38, 52},
		{1, 5, 7, 21, 23, 37, 39, 53},
		{2, 8, 19, 24, 34, 40, 50, 54},
		{3, 9, 18, 25, 35, 41, 51, 55},
		{10, 17, 26, 30, 42, 46, 56, 60},
		{11, 16, 27, 31, 43, 47, 57, 61},
		{12, 15, 28, 32, 44, 48, 58, 62},
		{13, 14, 29, 33, 45, 49, 59, 63},
	},
}

func sign(i int32) int32 {
	if i > 0 {
		return 1
	} else if i < 0 {
		return -1
	}
	return 0
}

type intermediaryblock [8][8]int32

func (self *VideoSequence) decode_block(cc int, macroblock_intra bool, b *block) error {
	var (
		QFS = b
		F   = b
	)

	var (
		QF  intermediaryblock
		Fpp intermediaryblock
		Fp  intermediaryblock
	)

	// inverse scan
	{
		alternate_scan := self.PictureCodingExtension.alternate_scan
		for v := 0; v < 8; v++ {
			for u := 0; u < 8; u++ {
				QF[v][u] = QFS[scan[alternate_scan][v][u]]
			}
		}
	}

	// Inverse quantisation
	{
		q_scale_type := self.PictureCodingExtension.q_scale_type
		quantiser_scale_code := self.currentQSC
		quantiser_scale := quantiser_scale_tables[q_scale_type][quantiser_scale_code]

		var w int
		if cc == 0 {
			if macroblock_intra {
				w = 0
			} else {
				w = 1
			}
		} else {
			if self.SequenceExtension.chroma_format == ChromaFormat_420 {
				if macroblock_intra {
					w = 0
				} else {
					w = 1
				}
			} else {
				if macroblock_intra {
					w = 2
				} else {
					w = 3
				}
			}
		}

		W := self.quantisationMatricies

		for v := 0; v < 8; v++ {
			for u := 0; u < 8; u++ {
				if (u == 0) && (v == 0) && (macroblock_intra) {
					// Table 7-4
					intra_dc_mult := int32(1) << (3 - self.PictureCodingExtension.intra_dc_precision)
					Fpp[v][u] = intra_dc_mult * QF[v][u]
				} else {
					if macroblock_intra {
						Fpp[v][u] = (QF[v][u] * int32(W[w][v][u]) * quantiser_scale * 2) / 32
					} else {
						Fpp[v][u] = (((QF[v][u] * 2) + sign(QF[v][u])) * int32(W[w][v][u]) *
							quantiser_scale) / 32
					}
				}
			}
		}
	}

	{
		// Saturation
		var sum int32 = 0
		for v := 0; v < 8; v++ {
			for u := 0; u < 8; u++ {
				if Fpp[v][u] > 2047 {
					Fp[v][u] = 2047
				} else if Fpp[v][u] < -2048 {
					Fp[v][u] = -2048
				} else {
					Fp[v][u] = Fpp[v][u]
				}
				sum = sum + Fp[v][u]
				F[v*8+u] = Fp[v][u]
			}
		}

		// Mismatch control
		if (sum & 1) == 0 {
			if (F[7*8+7] & 1) != 0 {
				F[7*8+7] = Fp[7][7] - 1
			} else {
				F[7*8+7] = Fp[7][7] + 1
			}
		}
	}

	return nil
}
<commit_msg>more explicit function name<commit_after>package video

var scan = [2][8][8]int{
	{
		{0, 1, 5, 6, 14, 15, 27, 28},
		{2, 4, 7, 13, 16, 26, 29, 42},
		{3, 8, 12, 17, 25, 30, 41, 43},
		{9, 11, 18, 24, 31, 40, 44, 53},
		{10, 19, 23, 32, 39, 45, 52, 54},
		{20, 22, 33, 38, 46, 51, 55, 60},
		{21, 34, 37, 47, 50, 56, 59, 61},
		{35, 36, 48, 49, 57, 58, 62, 63},
	},
	{
		{0, 4, 6, 20, 22, 36, 38, 52},
		{1, 5, 7, 21, 23, 37, 39, 53},
		{2, 8, 19, 24, 34, 40, 50, 54},
		{3, 9, 18, 25, 35, 41, 51, 55},
		{10, 17, 26, 30, 42, 46, 56, 60},
		{11, 16, 27, 31, 43, 47, 57, 61},
		{12, 15, 28, 32, 44, 48, 58, 62},
		{13, 14, 29, 33, 45, 49, 59, 63},
	},
}

func signInt32(i int32) int32 {
	if i > 0 {
		return 1
	} else if i < 0 {
		return -1
	}
	return 0
}

type intermediaryblock [8][8]int32

func (self *VideoSequence) decode_block(cc int, macroblock_intra bool, b *block) error {
	var (
		QFS = b
		F   = b
	)

	var (
		QF  intermediaryblock
		Fpp intermediaryblock
		Fp  intermediaryblock
	)

	// inverse scan
	{
		alternate_scan := self.PictureCodingExtension.alternate_scan
		for v := 0; v < 8; v++ {
			for u := 0; u < 8; u++ {
				QF[v][u] = QFS[scan[alternate_scan][v][u]]
			}
		}
	}

	// Inverse quantisation
	{
		q_scale_type := self.PictureCodingExtension.q_scale_type
		quantiser_scale_code := self.currentQSC
		quantiser_scale := quantiser_scale_tables[q_scale_type][quantiser_scale_code]

		var w int
		if cc == 0 {
			if macroblock_intra {
				w = 0
			} else {
				w = 1
			}
		} else {
			if self.SequenceExtension.chroma_format == ChromaFormat_420 {
				if macroblock_intra {
					w = 0
				} else {
					w = 1
				}
			} else {
				if macroblock_intra {
					w = 2
				} else {
					w = 3
				}
			}
		}

		W := self.quantisationMatricies

		for v := 0; v < 8; v++ {
			for u := 0; u < 8; u++ {
				if (u == 0) && (v == 0) && (macroblock_intra) {
					// Table 7-4
					intra_dc_mult := int32(1) << (3 - self.PictureCodingExtension.intra_dc_precision)
					Fpp[v][u] = intra_dc_mult * QF[v][u]
				} else {
					if macroblock_intra {
						Fpp[v][u] = (QF[v][u] * int32(W[w][v][u]) * quantiser_scale * 2) / 32
					} else {
						Fpp[v][u] = (((QF[v][u] * 2) + signInt32(QF[v][u])) * int32(W[w][v][u]) *
							quantiser_scale) / 32
					}
				}
			}
		}
	}

	{
		// Saturation
		var sum int32 = 0
		for v := 0; v < 8; v++ {
			for u := 0; u < 8; u++ {
				if Fpp[v][u] > 2047 {
					Fp[v][u] = 2047
				} else if Fpp[v][u] < -2048 {
					Fp[v][u] = -2048
				} else {
					Fp[v][u] = Fpp[v][u]
				}
				sum = sum + Fp[v][u]
				F[v*8+u] = Fp[v][u]
			}
		}

		// Mismatch control
		if (sum & 1) == 0 {
			if (F[7*8+7] & 1) != 0 {
				F[7*8+7] = Fp[7][7] - 1
			} else {
				F[7*8+7] = Fp[7][7] + 1
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>//
// message.go
//
package main

import (
  "bufio"
  "log"
  "os"
  "strings"
  "time"
)

type NNTPAttachment struct {
  filename string
  data string
}

type NNTPMessage struct {
  MessageID string
  Reference string
  Newsgroup string
  Name string
  Email string
  Subject string
  PubKey string
  Signature string
  Posted time.Time
  Message string
  Path string
  ContentType string
  Sage bool
  Attachments []NNTPAttachment
}

// load headers from file
func (self *NNTPMessage) LoadHeaders(file *os.File) bool {
  reader := bufio.NewReader(file)
  var idx int
  for {
    line, err := reader.ReadString('\n')
    if err != nil {
      log.Println("failed to read message", file.Name())
      return false
    }
    // we are done reading headers
    // break out
    if line == "\n" {
      break
    }
    lowline := strings.ToLower(line)
    llen := len(line)
    // check newsgroup header
    if strings.HasPrefix(lowline, "newsgroups: ") {
      newsgroups:= line[12:llen-1]
      idx = strings.Index(newsgroups, ",")
      if idx != -1 {
        newsgroups = newsgroups[:idx]
      }
      self.Newsgroup = newsgroups
    } else if strings.HasPrefix(lowline, "x-sage: ") {
      self.Sage = true
    } else if strings.HasPrefix(lowline, "message-id: ") {
      self.MessageID = line[12:llen-1]
    } else if strings.HasPrefix(lowline, "subject: ") {
      self.Subject = line[9:llen-1]
    } else if strings.HasPrefix(lowline, "path: ") {
      self.Path = line[6:llen-1]
    } else if strings.HasPrefix(lowline, "reference: ") {
      self.Reference = line[11:llen-1]
    } else if strings.HasPrefix(lowline, "from: ") {
      line = line[6:llen-1]
      llen = len(line)
      idx = strings.LastIndex(line, " ")
      if 1 + idx < llen {
        self.Name = line[:idx]
        self.Email = line[idx+2:llen-1]
      } else {
        self.Name = line
      }
    } else if strings.HasPrefix(lowline, "x-pubkey-ed25519: ") {
      self.PubKey = line[18:llen-1]
    } else if strings.HasPrefix(lowline, "x-signature-ed25519-sha512: ") {
      self.Signature = line[28:llen-1]
    } else if strings.HasPrefix(lowline, "date: ") {
      date, err := time.Parse(time.RFC1123Z, line[6:llen-1])
      if err == nil {
        self.Posted = date
      }
    } else if strings.HasPrefix(lowline, "content-type: ") {
      self.ContentType = line[14:llen-1]
    }
  }

  return true

}

// load body
// TODO: implement
func (self *NNTPMessage) LoadBody(file *os.File) bool {
  return false
}
<commit_msg>fix slice out of bounds<commit_after>//
// message.go
//
package main

import (
  "bufio"
  "log"
  "os"
  "strings"
  "time"
)

type NNTPAttachment struct {
  filename string
  data string
}

type NNTPMessage struct {
  MessageID string
  Reference string
  Newsgroup string
  Name string
  Email string
  Subject string
  PubKey string
  Signature string
  Posted time.Time
  Message string
  Path string
  ContentType string
  Sage bool
  Attachments []NNTPAttachment
}

// load headers from file
func (self *NNTPMessage) LoadHeaders(file *os.File) bool {
  reader := bufio.NewReader(file)
  var idx int
  for {
    line, err := reader.ReadString('\n')
    if err != nil {
      log.Println("failed to read message", file.Name())
      return false
    }
    // we are done reading headers
    // break out
    if line == "\n" {
      break
    }
    lowline := strings.ToLower(line)
    llen := len(line)
    // check newsgroup header
    if strings.HasPrefix(lowline, "newsgroups: ") {
      newsgroups:= line[12:llen-1]
      idx = strings.Index(newsgroups, ",")
      if idx != -1 {
        newsgroups = newsgroups[:idx]
      }
      self.Newsgroup = newsgroups
    } else if strings.HasPrefix(lowline, "x-sage: ") {
      self.Sage = true
    } else if strings.HasPrefix(lowline, "message-id: ") {
      self.MessageID = line[12:llen-1]
    } else if strings.HasPrefix(lowline, "subject: ") {
      self.Subject = line[9:llen-1]
    } else if strings.HasPrefix(lowline, "path: ") {
      self.Path = line[6:llen-1]
    } else if strings.HasPrefix(lowline, "reference: ") {
      self.Reference = line[11:llen-1]
    } else if strings.HasPrefix(lowline, "from: ") {
      line = line[6:llen-1]
      llen = len(line)
      idx = strings.LastIndex(line, " ")
      if 1 + idx < llen {
        self.Name = line[:idx]
        self.Email = line[idx+1:llen-1]
      } else {
        self.Name = line
      }
    } else if strings.HasPrefix(lowline, "x-pubkey-ed25519: ") {
      self.PubKey = line[18:llen-1]
    } else if strings.HasPrefix(lowline, "x-signature-ed25519-sha512: ") {
      self.Signature = line[28:llen-1]
    } else if strings.HasPrefix(lowline, "date: ") {
      date, err := time.Parse(time.RFC1123Z, line[6:llen-1])
      if err == nil {
        self.Posted = date
      }
    } else if strings.HasPrefix(lowline, "content-type: ") {
      self.ContentType = line[14:llen-1]
    }
  }

  return true

}

// load body
// TODO: implement
func (self *NNTPMessage) LoadBody(file *os.File) bool {
  return false
}
<|endoftext|>


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

package dns

import (
	"net"
	"time"
)

// Envelope is used when doing a transfer with a remote server.
type Envelope struct {
	RR    []RR  // The set of RRs in the answer section of the AXFR reply message.
	Error error // If something went wrong, this contains the error.
}

type Transfer struct {
	Conn
	DialTimeout    time.Duration // net.DialTimeout (ns), defaults to 2 * 1e9
	ReadTimeout    time.Duration // net.Conn.SetReadTimeout value for connections (ns), defaults to 2 * 1e9
	WriteTimeout   time.Duration // net.Conn.SetWriteTimeout value for connections (ns), defaults to 2 * 1e9
	tsigTimersOnly bool
}

// In performs a [AI]XFR request (depends on the message's Qtype). It returns
// a channel of *Envelope on which the replies from the server are sent.
// At the end of the transfer the channel is closed.
// The messages are TSIG checked if needed, no other post-processing is performed.
// The caller must dissect the returned messages.
//
// Basic use pattern for receiving an AXFR:
//
//	// m contains the AXFR request
//	t := new(dns.Transfer)
//	c, e := t.In(m, "127.0.0.1:53")
//	for env := range c
//		// ... deal with env.RR or env.Error
//	}

func (t *Transfer) In(q *Msg, a string, env chan *Envelope) (err error) {
	co := new(Conn)
	timeout := dnsTimeout
	if t.DialTimeout != 0 {
		timeout = t.DialTimeout
	}
	co.Conn, err = net.DialTimeout("tcp", a, timeout)
	if err != nil {
		return err
	}
	if q.Question[0].Qtype == TypeAXFR {
		go t.InAxfr(q.Id, env)
		return nil
	}
	if q.Question[0].Qtype == TypeIXFR {
		go t.InAxfr(q.Id, env)
		return nil
	}
	return nil // TODO(miek): some error
}

func (t *Transfer) InAxfr(id uint16, c chan *Envelope) {
	first := true
	defer t.Close()
	defer close(c)
	timeout := dnsTimeout
	if t.ReadTimeout != 0 {
		timeout = t.ReadTimeout
	}
	for {
		t.SetReadDeadline(time.Now().Add(timeout))
		in, err := t.ReadMsg()
		if err != nil {
			c <- &Envelope{nil, err}
			return
		}
		if id != in.Id {
			c <- &Envelope{in.Answer, ErrId}
			return
		}
		if first {
			if !isSOAFirst(in) {
				c <- &Envelope{in.Answer, ErrSoa}
				return
			}
			first = !first
			// only one answer that is SOA, receive more
			if len(in.Answer) == 1 {
				t.tsigTimersOnly = true
				c <- &Envelope{in.Answer, nil}
				continue
			}
		}

		if !first {
			t.tsigTimersOnly = true // Subsequent envelopes use this.
			if isSOALast(in) {
				c <- &Envelope{in.Answer, nil}
				return
			}
			c <- &Envelope{in.Answer, nil}
		}
	}
	panic("dns: not reached")
}

func (t *Transfer) InIxfr(id uint16, c chan *Envelope) {
	serial := uint32(0) // The first serial seen is the current server serial
	first := true
	defer t.Close()
	defer close(c)
	timeout := dnsTimeout
	if t.ReadTimeout != 0 {
		timeout = t.ReadTimeout
	}
	for {
		// re-read 'n stuff must be pushed down
		t.SetReadDeadline(time.Now().Add(timeout))
		in, err := t.ReadMsg()
		if err != nil {
			c <- &Envelope{in.Answer, err}
			return
		}
		if id != in.Id {
			c <- &Envelope{in.Answer, ErrId}
			return
		}
		if first {
			// A single SOA RR signals "no changes"
			if len(in.Answer) == 1 && isSOAFirst(in) {
				c <- &Envelope{in.Answer, nil}
				return
			}

			// Check if the returned answer is ok
			if !isSOAFirst(in) {
				c <- &Envelope{in.Answer, ErrSoa}
				return
			}
			// This serial is important
			serial = in.Answer[0].(*SOA).Serial
			first = !first
			// continue // TODO(miek)
		}

		// Now we need to check each message for SOA records, to see what we need to do
		if !first {
			t.tsigTimersOnly = true
			// If the last record in the IXFR contains the servers' SOA,  we should quit
			if v, ok := in.Answer[len(in.Answer)-1].(*SOA); ok {
				if v.Serial == serial {
					c <- &Envelope{in.Answer, nil}
					return
				}
			}
			c <- &Envelope{in.Answer, nil}
		}
	}
}

func (t *Transfer) Out(w ResponseWriter, q *Msg, a string) (chan *Envelope, error) {
	ch := make(chan *Envelope)
	r := new(Msg)
	r.SetReply(q)
	r.Authoritative = true
	go func() {
		for x := range ch {
			// assume it fits TODO(miek): fix
			r.Answer = append(r.Answer, x.RR...)
			if err := w.WriteMsg(r); err != nil {
				return
			}
		}
		//		w.TsigTimersOnly(true)
		//		rep.Answer = nil
	}()
	return ch, nil
}

// ReadMsg reads a message from the transfer connection t.
func (t *Transfer) ReadMsg() (*Msg, error) {
	m := new(Msg)
	p := make([]byte, MaxMsgSize)
	n, err := t.Read(p)
	if err != nil && n == 0 {
		return nil, err
	}
	p = p[:n]
	if err := m.Unpack(p); err != nil {
		return nil, err
	}
	if ts := m.IsTsig(); t != nil {
		if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
			return m, ErrSecret
		}
		// Need to work on the original message p, as that was used to calculate the tsig.
		err = TsigVerify(p, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
	}
	return m, err
}

// WriteMsg write a message throught the transfer connection t.
func (t *Transfer) WriteMsg(m *Msg) (err error) {
	var out []byte
	if ts := m.IsTsig(); t != nil {
		if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
			return ErrSecret
		}
		out, t.tsigRequestMAC, err = TsigGenerate(m, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
	} else {
		out, err = m.Pack()
	}
	if err != nil {
		return err
	}
	if _, err = t.Write(out); err != nil {
		return err
	}
	return nil
}

/*

*/

func isSOAFirst(in *Msg) bool {
	if len(in.Answer) > 0 {
		return in.Answer[0].Header().Rrtype == TypeSOA
	}
	return false
}

func isSOALast(in *Msg) bool {
	if len(in.Answer) > 0 {
		return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
	}
	return false
}
<commit_msg>make these methods privates<commit_after>// Copyright 2011 Miek Gieben. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package dns

import (
	"net"
	"time"
)

// Envelope is used when doing a transfer with a remote server.
type Envelope struct {
	RR    []RR  // The set of RRs in the answer section of the AXFR reply message.
	Error error // If something went wrong, this contains the error.
}

type Transfer struct {
	Conn
	DialTimeout    time.Duration // net.DialTimeout (ns), defaults to 2 * 1e9
	ReadTimeout    time.Duration // net.Conn.SetReadTimeout value for connections (ns), defaults to 2 * 1e9
	WriteTimeout   time.Duration // net.Conn.SetWriteTimeout value for connections (ns), defaults to 2 * 1e9
	tsigTimersOnly bool
}

// In performs a [AI]XFR request (depends on the message's Qtype). It returns
// a channel of *Envelope on which the replies from the server are sent.
// At the end of the transfer the channel is closed.
// The messages are TSIG checked if needed, no other post-processing is performed.
// The caller must dissect the returned messages.
//
// Basic use pattern for receiving an AXFR:
//
//	// m contains the AXFR request
//	t := new(dns.Transfer)
//	c, e := t.In(m, "127.0.0.1:53")
//	for env := range c
//		// ... deal with env.RR or env.Error
//	}

func (t *Transfer) In(q *Msg, a string, env chan *Envelope) (err error) {
	co := new(Conn)
	timeout := dnsTimeout
	if t.DialTimeout != 0 {
		timeout = t.DialTimeout
	}
	co.Conn, err = net.DialTimeout("tcp", a, timeout)
	if err != nil {
		return err
	}
	if q.Question[0].Qtype == TypeAXFR {
		go t.inAxfr(q.Id, env)
		return nil
	}
	if q.Question[0].Qtype == TypeIXFR {
		go t.inIxfr(q.Id, env)
		return nil
	}
	return nil // TODO(miek): some error
}

func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
	first := true
	defer t.Close()
	defer close(c)
	timeout := dnsTimeout
	if t.ReadTimeout != 0 {
		timeout = t.ReadTimeout
	}
	for {
		t.SetReadDeadline(time.Now().Add(timeout))
		in, err := t.ReadMsg()
		if err != nil {
			c <- &Envelope{nil, err}
			return
		}
		if id != in.Id {
			c <- &Envelope{in.Answer, ErrId}
			return
		}
		if first {
			if !isSOAFirst(in) {
				c <- &Envelope{in.Answer, ErrSoa}
				return
			}
			first = !first
			// only one answer that is SOA, receive more
			if len(in.Answer) == 1 {
				t.tsigTimersOnly = true
				c <- &Envelope{in.Answer, nil}
				continue
			}
		}

		if !first {
			t.tsigTimersOnly = true // Subsequent envelopes use this.
			if isSOALast(in) {
				c <- &Envelope{in.Answer, nil}
				return
			}
			c <- &Envelope{in.Answer, nil}
		}
	}
	panic("dns: not reached")
}

func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
	serial := uint32(0) // The first serial seen is the current server serial
	first := true
	defer t.Close()
	defer close(c)
	timeout := dnsTimeout
	if t.ReadTimeout != 0 {
		timeout = t.ReadTimeout
	}
	for {
		// re-read 'n stuff must be pushed down
		t.SetReadDeadline(time.Now().Add(timeout))
		in, err := t.ReadMsg()
		if err != nil {
			c <- &Envelope{in.Answer, err}
			return
		}
		if id != in.Id {
			c <- &Envelope{in.Answer, ErrId}
			return
		}
		if first {
			// A single SOA RR signals "no changes"
			if len(in.Answer) == 1 && isSOAFirst(in) {
				c <- &Envelope{in.Answer, nil}
				return
			}

			// Check if the returned answer is ok
			if !isSOAFirst(in) {
				c <- &Envelope{in.Answer, ErrSoa}
				return
			}
			// This serial is important
			serial = in.Answer[0].(*SOA).Serial
			first = !first
			// continue // TODO(miek)
		}

		// Now we need to check each message for SOA records, to see what we need to do
		if !first {
			t.tsigTimersOnly = true
			// If the last record in the IXFR contains the servers' SOA,  we should quit
			if v, ok := in.Answer[len(in.Answer)-1].(*SOA); ok {
				if v.Serial == serial {
					c <- &Envelope{in.Answer, nil}
					return
				}
			}
			c <- &Envelope{in.Answer, nil}
		}
	}
}

func (t *Transfer) Out(w ResponseWriter, q *Msg, a string) (chan *Envelope, error) {
	ch := make(chan *Envelope)
	r := new(Msg)
	r.SetReply(q)
	r.Authoritative = true
	go func() {
		for x := range ch {
			// assume it fits TODO(miek): fix
			r.Answer = append(r.Answer, x.RR...)
			if err := w.WriteMsg(r); err != nil {
				return
			}
		}
		//		w.TsigTimersOnly(true)
		//		rep.Answer = nil
	}()
	return ch, nil
}

// ReadMsg reads a message from the transfer connection t.
func (t *Transfer) ReadMsg() (*Msg, error) {
	m := new(Msg)
	p := make([]byte, MaxMsgSize)
	n, err := t.Read(p)
	if err != nil && n == 0 {
		return nil, err
	}
	p = p[:n]
	if err := m.Unpack(p); err != nil {
		return nil, err
	}
	if ts := m.IsTsig(); t != nil {
		if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
			return m, ErrSecret
		}
		// Need to work on the original message p, as that was used to calculate the tsig.
		err = TsigVerify(p, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
	}
	return m, err
}

// WriteMsg write a message throught the transfer connection t.
func (t *Transfer) WriteMsg(m *Msg) (err error) {
	var out []byte
	if ts := m.IsTsig(); t != nil {
		if _, ok := t.TsigSecret[ts.Hdr.Name]; !ok {
			return ErrSecret
		}
		out, t.tsigRequestMAC, err = TsigGenerate(m, t.TsigSecret[ts.Hdr.Name], t.tsigRequestMAC, t.tsigTimersOnly)
	} else {
		out, err = m.Pack()
	}
	if err != nil {
		return err
	}
	if _, err = t.Write(out); err != nil {
		return err
	}
	return nil
}

/*

*/

func isSOAFirst(in *Msg) bool {
	if len(in.Answer) > 0 {
		return in.Answer[0].Header().Rrtype == TypeSOA
	}
	return false
}

func isSOALast(in *Msg) bool {
	if len(in.Answer) > 0 {
		return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
	}
	return false
}
<|endoftext|>


<commit_before>// Package xhr provides GopherJS bindings for the XMLHttpRequest API.
//
// This package provides two ways of using XHR. The first one is via
// the Request type and the NewRequest function. This way, one can
// specify all desired details of the request's behaviour (timeout,
// response format). It also allows access to response details such as
// the status code. Furthermore, using this way is required if one
// wants to abort in-flight requests.
//
//   r := xhr.NewRequest()
//   r.SetTimeout(time.Second)
//   r.ResponseType = "document"
//   r.Open("GET", "/endpoint", "", "")
//   err := r.Send(nil)
//   if err != nil { handle_error() }
//   // r.Response will contain a JavaScript Document element that can
//   // for example be used with the js/dom package.
//
//
// The other way is via the package function Send, which is a helper
// that constructs a Request internally and assigns sane defaults to
// it. It's the easiest way of doing an XHR request that should just
// return unprocessed data.
//
//     data, err := xhr.Send("GET", "/endpoint", "", "", nil)
//     if err != nil { handle_error() }
//     console.Log("Retrieved data", data)
package xhr

import (
	"errors"

	"github.com/gopherjs/gopherjs/js"
)

const (
	Unsent = iota
	Opened
	HeadersReceived
	Loading
	Done
)

// Request wraps an XMLHttpRequest. New instances have to be created
// with NewRequest. Each instance may only be used for a single
// request.
type Request struct {
	js.Object
	ReadyState      int       `js:"readyState"`
	Response        js.Object `js:"response"`
	ResponseText    string    `js:"responseText"`
	ResponseType    string    `js:"responseType"`
	ResponseXML     js.Object `js:"responseXML"`
	Status          int       `js:"status"`
	StatusText      string    `js:"statusText"`
	Timeout         int       `js:"timeout"`
	Upload          js.Object `js:"upload"`
	WithCredentials bool      `js:"withCredentials"`
	// TODO provide callbacks for upload, state change and load
	ch chan error
}

// ErrAborted is the error returned by Send when a request was
// aborted.
var ErrAborted = errors.New("request aborted")

// ErrTimeout is the error returned by Send when a request timed out.
var ErrTimeout = errors.New("request timed out")

// NewRequest creates a new XMLHttpRequest object, which may be used
// for a single request.
func NewRequest() *Request {
	o := js.Global.Get("XMLHttpRequest").New()
	return &Request{Object: o}
}

// ResponseHeaders returns all response headers.
func (r *Request) ResponseHeaders() string {
	return r.Call("getAllResponseHeaders").Str()
}

// ResponseHeader returns the value of the specified header.
func (r *Request) ResponseHeader(name string) string {
	value := r.Call("getResponseHeader", name)
	if value.IsNull() {
		return ""
	}
	return value.Str()
}

// Abort will abort the request. The corresponding Send will return
// ErrAborted.
func (r *Request) Abort() {
	if r.ch == nil {
		return
	}

	r.Call("abort")
	select {
	case r.ch <- ErrAborted:
	default:
	}
}

func (r *Request) Open(method, url, user, password string) {
	// TODO "is the equivalent of calling abort()" – does that mean
	// ONLY abort, or also a new request? also check the behaviour re
	// the TODO in Abort.

	if r.ch != nil {
		panic("must not use a Request for multiple requests")
	}
	r.Call("open", method, url, true, user, password)
}

func (r *Request) OverrideMimeType(mimetype string) {
	r.Call("overrideMimeType", mimetype)
}

func (r *Request) Send(data interface{}) error {
	if r.ch != nil {
		panic("must not use a Request for multiple requests")
	}
	r.ch = make(chan error, 1)
	r.Call("addEventListener", "load", func() {
		go func() { r.ch <- nil }()
	})
	r.Call("addEventListener", "error", func(o js.Object) {
		go func() { r.ch <- &js.Error{Object: o} }()
	})
	r.Call("addEventListener", "timeout", func() {
		go func() { r.ch <- ErrTimeout }()
	})
	r.Call("send", data)
	val := <-r.ch
	return val
}

func (r *Request) SetRequestHeader(header, value string) {
	r.Call("setRequestHeader", header, value)
}

func Send(method, url, user, password string, data interface{}) (string, error) {
	xhr := NewRequest()
	xhr.Open(method, url, user, password)
	err := xhr.Send(data)
	if err != nil {
		return "", err
	}
	return xhr.ResponseText, nil
}
<commit_msg>add Upload type<commit_after>// Package xhr provides GopherJS bindings for the XMLHttpRequest API.
//
// This package provides two ways of using XHR. The first one is via
// the Request type and the NewRequest function. This way, one can
// specify all desired details of the request's behaviour (timeout,
// response format). It also allows access to response details such as
// the status code. Furthermore, using this way is required if one
// wants to abort in-flight requests.
//
//   r := xhr.NewRequest()
//   r.SetTimeout(time.Second)
//   r.ResponseType = "document"
//   r.Open("GET", "/endpoint", "", "")
//   err := r.Send(nil)
//   if err != nil { handle_error() }
//   // r.Response will contain a JavaScript Document element that can
//   // for example be used with the js/dom package.
//
//
// The other way is via the package function Send, which is a helper
// that constructs a Request internally and assigns sane defaults to
// it. It's the easiest way of doing an XHR request that should just
// return unprocessed data.
//
//     data, err := xhr.Send("GET", "/endpoint", "", "", nil)
//     if err != nil { handle_error() }
//     console.Log("Retrieved data", data)
package xhr

import (
	"errors"

	"github.com/gopherjs/gopherjs/js"
	"honnef.co/go/js/util"
)

const (
	Unsent = iota
	Opened
	HeadersReceived
	Loading
	Done
)

// Request wraps an XMLHttpRequest. New instances have to be created
// with NewRequest. Each instance may only be used for a single
// request.
type Request struct {
	js.Object
	ReadyState      int       `js:"readyState"`
	Response        js.Object `js:"response"`
	ResponseText    string    `js:"responseText"`
	ResponseType    string    `js:"responseType"`
	ResponseXML     js.Object `js:"responseXML"`
	Status          int       `js:"status"`
	StatusText      string    `js:"statusText"`
	Timeout         int       `js:"timeout"`
	WithCredentials bool      `js:"withCredentials"`
	// TODO provide callbacks for upload, state change and load

	ch chan error
}

// Upload wraps XMLHttpRequestUpload objects.
type Upload struct {
	js.Object
	util.EventTarget
}

// Upload returns the XMLHttpRequestUpload object associated with the
// request. It can be used to register events for tracking the
// progress of uploads.
func (r *Request) Upload() *Upload {
	o := r.Get("upload")
	return &Upload{o, util.EventTarget{Object: o}}
}

// ErrAborted is the error returned by Send when a request was
// aborted.
var ErrAborted = errors.New("request aborted")

// ErrTimeout is the error returned by Send when a request timed out.
var ErrTimeout = errors.New("request timed out")

// NewRequest creates a new XMLHttpRequest object, which may be used
// for a single request.
func NewRequest() *Request {
	o := js.Global.Get("XMLHttpRequest").New()
	return &Request{Object: o}
}

// ResponseHeaders returns all response headers.
func (r *Request) ResponseHeaders() string {
	return r.Call("getAllResponseHeaders").Str()
}

// ResponseHeader returns the value of the specified header.
func (r *Request) ResponseHeader(name string) string {
	value := r.Call("getResponseHeader", name)
	if value.IsNull() {
		return ""
	}
	return value.Str()
}

// Abort will abort the request. The corresponding Send will return
// ErrAborted.
func (r *Request) Abort() {
	if r.ch == nil {
		return
	}

	r.Call("abort")
	select {
	case r.ch <- ErrAborted:
	default:
	}
}

func (r *Request) Open(method, url, user, password string) {
	// TODO "is the equivalent of calling abort()" – does that mean
	// ONLY abort, or also a new request? also check the behaviour re
	// the TODO in Abort.

	if r.ch != nil {
		panic("must not use a Request for multiple requests")
	}
	r.Call("open", method, url, true, user, password)
}

func (r *Request) OverrideMimeType(mimetype string) {
	r.Call("overrideMimeType", mimetype)
}

func (r *Request) Send(data interface{}) error {
	if r.ch != nil {
		panic("must not use a Request for multiple requests")
	}
	r.ch = make(chan error, 1)
	r.Call("addEventListener", "load", func() {
		go func() { r.ch <- nil }()
	})
	r.Call("addEventListener", "error", func(o js.Object) {
		go func() { r.ch <- &js.Error{Object: o} }()
	})
	r.Call("addEventListener", "timeout", func() {
		go func() { r.ch <- ErrTimeout }()
	})
	r.Call("send", data)
	val := <-r.ch
	return val
}

func (r *Request) SetRequestHeader(header, value string) {
	r.Call("setRequestHeader", header, value)
}

func Send(method, url, user, password string, data interface{}) (string, error) {
	xhr := NewRequest()
	xhr.Open(method, url, user, password)
	err := xhr.Send(data)
	if err != nil {
		return "", err
	}
	return xhr.ResponseText, nil
}
<|endoftext|>


<commit_before>package xpp

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io"
)

type XMLEventType int

const (
	StartDocument XMLEventType = iota
	EndDocument
	StartTag
	EndTag
	Text
	Comment
	ProcessingInstruction
	Directive
	// TODO: IgnorableWhitespace ?
	// TODO: CDSECT ?
)

type XMLPullParser struct {
	Depth       int
	Event       XMLEventType
	Attrs       []xml.Attr
	Name        string
	SpacePrefix string
	Space       string
	Text        string

	decoder *xml.Decoder
	token   interface{}
}

func NewXMLPullParser(r io.Reader) *XMLPullParser {
	d := xml.NewDecoder(r)
	d.Strict = false
	return &XMLPullParser{decoder: d, token: StartDocument, Depth: 0}
}

func (p *XMLPullParser) NextTag() (event XMLEventType, err error) {
	t, err := p.Next()
	if err != nil {
		return
	}

	if t != StartTag && t != EndTag {
		return event, errors.New("Expected StartTag or EndTag")
	}

	return t, nil
}

func (p *XMLPullParser) Next() (event XMLEventType, err error) {
	for {
		event, err := p.NextToken()
		if err != nil {
			return event, err
		}
		if event == StartTag ||
			event == EndTag ||
			event == Text ||
			event == EndDocument {
			break
		}
	}
	return event, nil
}

func (p *XMLPullParser) NextToken() (event XMLEventType, err error) {
	// Clear any state held for the previous token
	p.resetTokenState()

	tok, err := p.decoder.Token()
	if err != nil {
		if err != io.EOF {
			return event, err
		}

		// XML decoder returns the EOF as an error
		// but we want to return it as a valid
		// EndDocument token instead
		p.token = nil
		p.processEndDocument()
		return p.Event, nil
	}

	p.token = xml.CopyToken(tok)
	switch tt := p.token.(type) {
	case xml.StartElement:
		p.processStartToken(tt)
	case xml.EndElement:
		p.processEndToken(tt)
	case xml.CharData:
		p.processTextToken(tt)
	case xml.Comment:
		p.processCommentToken(tt)
	case xml.ProcInst:
		p.processProcInstToken(tt)
	case xml.Directive:
		p.processDirectiveToken(tt)
	}

	return p.Event, nil
}

func (p *XMLPullParser) NextText() (string, error) {
	if p.Event != StartTag {
		return "", errors.New("Parser must be on StartTag to get NextText()")
	}

	t, err := p.Next()
	if err != nil {
		return "", err
	}

	if t == Text {
		result := p.Text
		nt, err := p.Next()
		if err != nil {
			return "", err
		}

		if nt != EndTag {
			return "", errors.New("Event Text must be immediately followed by EndTag")
		}

		return result, nil
	} else if t == EndTag {
		return "", nil
	} else {
		return "", errors.New("Parser must be on StartTag or Text to read text")
	}
}

func (p *XMLPullParser) Skip() error {
	for {
		tok, err := p.NextToken()
		if err != nil {
			return err
		}
		if tok == StartTag {
			if err := p.Skip(); err != nil {
				return err
			}
		} else if tok == EndTag {
			return nil
		}
	}
}

func (p *XMLPullParser) Attribute(name string) string {
	for _, attr := range p.Attrs {
		if attr.Name.Local == name {
			return attr.Value
		}
	}
	return ""
}

func (p *XMLPullParser) Matches(event XMLEventType, namespace *string, name *string) bool {
	return p.Event == event && (namespace == nil || p.Space == *namespace) && (name == nil || p.Name == *name)
}

func (p *XMLPullParser) processStartToken(t xml.StartElement) {
	p.Depth++
	p.Event = StartTag
	p.Attrs = t.Attr
	p.Name = t.Name.Local
	p.Space = t.Name.Space
}

func (p *XMLPullParser) processEndToken(t xml.EndElement) {
	p.Depth--
	p.Event = EndTag
	p.Name = t.Name.Local

}

func (p *XMLPullParser) processTextToken(t xml.CharData) {
	p.Event = Text
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) processCommentToken(t xml.Comment) {
	p.Event = Comment
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) processProcInstToken(t xml.ProcInst) {
	p.Event = ProcessingInstruction
	p.Text = fmt.Sprintf("%s %s", t.Target, string(t.Inst))
}

func (p *XMLPullParser) processDirectiveToken(t xml.Directive) {
	p.Event = Directive
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) processEndDocument() {
	p.Event = EndDocument
}

func (p *XMLPullParser) resetTokenState() {
	p.Attrs = nil
	p.Name = ""
	p.Space = ""
	p.Text = ""
}
<commit_msg>Add ignorable text token<commit_after>package xpp

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"strings"
)

type XMLEventType int

const (
	StartDocument XMLEventType = iota
	EndDocument
	StartTag
	EndTag
	Text
	Comment
	ProcessingInstruction
	Directive
	IgnorableWhitespace
	// TODO: CDSECT ?
)

type XMLPullParser struct {
	Depth       int
	Event       XMLEventType
	Attrs       []xml.Attr
	Name        string
	SpacePrefix string
	Space       string
	Text        string

	decoder *xml.Decoder
	token   interface{}
}

func NewXMLPullParser(r io.Reader) *XMLPullParser {
	d := xml.NewDecoder(r)
	d.Strict = false
	return &XMLPullParser{decoder: d, token: StartDocument, Depth: 0}
}

func (p *XMLPullParser) NextTag() (event XMLEventType, err error) {
	t, err := p.Next()
	if err != nil {
		return
	}

	if t != StartTag && t != EndTag {
		fmt.Printf("Whoops - got token %d - %s - %sxx\n", t, p.Name, p.Text)
		return event, errors.New("Expected StartTag or EndTag.")
	}

	return t, nil
}

func (p *XMLPullParser) Next() (event XMLEventType, err error) {
	for {
		event, err = p.NextToken()
		if err != nil {
			return event, err
		}

		if event == StartTag ||
			event == EndTag ||
			event == Text ||
			event == EndDocument {
			break
		}
	}
	return event, nil
}

func (p *XMLPullParser) NextToken() (event XMLEventType, err error) {
	// Clear any state held for the previous token
	p.resetTokenState()

	tok, err := p.decoder.Token()
	if err != nil {
		if err != io.EOF {
			return event, err
		}

		// XML decoder returns the EOF as an error
		// but we want to return it as a valid
		// EndDocument token instead
		p.token = nil
		p.Event = EndDocument
		return p.Event, nil
	}

	p.token = xml.CopyToken(tok)
	switch tt := p.token.(type) {
	case xml.StartElement:
		p.processStartToken(tt)
	case xml.EndElement:
		p.processEndToken(tt)
	case xml.CharData:
		p.processCharDataToken(tt)
	case xml.Comment:
		p.processCommentToken(tt)
	case xml.ProcInst:
		p.processProcInstToken(tt)
	case xml.Directive:
		p.processDirectiveToken(tt)
	}

	fmt.Printf("Consumed token: %d - %s\n", p.Event, p.token)

	return p.Event, nil
}

func (p *XMLPullParser) NextText() (string, error) {
	if p.Event != StartTag {
		return "", errors.New("Parser must be on StartTag to get NextText()")
	}

	t, err := p.Next()
	if err != nil {
		return "", err
	}

	if t == Text {
		result := p.Text
		nt, err := p.Next()
		if err != nil {
			return "", err
		}

		if nt != EndTag {
			return "", errors.New("Event Text must be immediately followed by EndTag")
		}

		return result, nil
	} else if t == EndTag {
		return "", nil
	} else {
		return "", errors.New("Parser must be on StartTag or Text to read text")
	}
}

func (p *XMLPullParser) Skip() error {
	for {
		tok, err := p.NextToken()
		if err != nil {
			return err
		}
		if tok == StartTag {
			if err := p.Skip(); err != nil {
				return err
			}
		} else if tok == EndTag {
			return nil
		}
	}
}

func (p *XMLPullParser) Attribute(name string) string {
	for _, attr := range p.Attrs {
		if attr.Name.Local == name {
			return attr.Value
		}
	}
	return ""
}

func (p *XMLPullParser) Matches(event XMLEventType, name string) bool {
	return p.Event == event && p.Name == name
}

func (p *XMLPullParser) MatchesAll(event XMLEventType, namespace string, name string) bool {
	return p.Event == event && p.Space == namespace && p.Name == name
}

func (p *XMLPullParser) processStartToken(t xml.StartElement) {
	p.Depth++
	p.Event = StartTag
	p.Attrs = t.Attr
	p.Name = t.Name.Local
	p.Space = t.Name.Space
}

func (p *XMLPullParser) processEndToken(t xml.EndElement) {
	p.Depth--
	p.Event = EndTag
	p.Name = t.Name.Local

}

func (p *XMLPullParser) processCharDataToken(t xml.CharData) {
	p.Text = string([]byte(t))
	p.Event = Text
	if p.isWhitespace() {
		p.Event = IgnorableWhitespace
	} else {
		p.Event = Text
	}
}

func (p *XMLPullParser) processCommentToken(t xml.Comment) {
	p.Event = Comment
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) processProcInstToken(t xml.ProcInst) {
	p.Event = ProcessingInstruction
	p.Text = fmt.Sprintf("%s %s", t.Target, string(t.Inst))
}

func (p *XMLPullParser) processDirectiveToken(t xml.Directive) {
	p.Event = Directive
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) resetTokenState() {
	p.Attrs = nil
	p.Name = ""
	p.Space = ""
	p.Text = ""
}

func (p *XMLPullParser) isWhitespace() bool {
	return strings.TrimSpace(p.Text) == ""
}
<|endoftext|>


<commit_before>package xpp

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"strings"
)

type XMLEventType int

const (
	StartDocument XMLEventType = iota
	EndDocument
	StartTag
	EndTag
	Text
	Comment
	ProcessingInstruction
	Directive
	IgnorableWhitespace // TODO: ?
	// TODO: CDSECT ?
)

type XMLPullParser struct {
	Depth int
	Event XMLEventType
	Attrs []xml.Attr
	Name  string
	Space string
	Text  string

	decoder   *xml.Decoder
	token     interface{}
	peekToken interface{}
	peekEvent XMLEventType
	peekErr   error
}

func NewXMLPullParser(r io.Reader) *XMLPullParser {
	d := xml.NewDecoder(r)
	d.Strict = false
	return &XMLPullParser{
		decoder: d,
		Event:   StartDocument,
		Depth:   0,
	}
}

func (p *XMLPullParser) NextTag() (event XMLEventType, err error) {
	t, err := p.Next()
	if err != nil {
		return
	}

	if t != StartTag && t != EndTag {
		return event, errors.New("Expected StartTag or EndTag.")
	}

	return t, nil
}

func (p *XMLPullParser) Next() (event XMLEventType, err error) {
	for {
		event, err = p.NextToken()
		if err != nil {
			return event, err
		}

		if event == Text {
			// Coalesce all contiguous text events together
			text := p.Text
			for p.peekEvent == Text && p.peekErr == nil {
				p.NextToken()
				text += p.Text
			}
			p.Text = text
			break
		}

		if event == StartTag ||
			event == EndTag ||
			event == EndDocument {
			break
		}
	}
	return event, nil
}

func (p *XMLPullParser) NextToken() (event XMLEventType, err error) {
	// Clear any state held for the previous token
	p.resetTokenState()

	// If there was an error when peeking return it now
	if p.peekErr != nil {
		return event, p.peekErr
	}

	// If the peek token was EndDocument, dont bother
	// retrieving any more tokens.  Just return EndDocument
	if p.peekEvent == EndDocument {
		return EndDocument, nil
	}

	// Switch peek token/event to the current token/event
	p.Event = p.peekEvent
	p.token = p.peekToken
	p.processToken(p.token)

	// Peek the next token/event
	peekToken, err := p.decoder.Token()
	if err != nil {
		if err != io.EOF {
			p.peekErr = err
		}

		// XML decoder returns the EOF as an error
		// but we want to return it as a valid
		// EndDocument token instead
		p.peekToken = nil
		p.peekEvent = EndDocument
	}
	p.peekToken = xml.CopyToken(peekToken)
	p.peekEvent = p.eventType(peekToken)

	// Return current event (previously the peek token)
	return p.Event, nil
}

func (p *XMLPullParser) NextText() (string, error) {
	if p.Event != StartTag {
		return "", errors.New("Parser must be on StartTag to get NextText()")
	}

	t, err := p.Next()
	if err != nil {
		return "", err
	}

	if t == Text {
		result := p.Text
		nt, err := p.Next()
		if err != nil {
			return "", err
		}

		if nt != EndTag {
			return "", errors.New("Event Text must be immediately followed by EndTag")
		}

		return result, nil
	} else if t == EndTag {
		return "", nil
	} else {
		return "", errors.New("Parser must be on StartTag or Text to read text")
	}
}

func (p *XMLPullParser) Skip() error {
	for {
		tok, err := p.NextToken()
		if err != nil {
			return err
		}
		if tok == StartTag {
			if err := p.Skip(); err != nil {
				return err
			}
		} else if tok == EndTag {
			return nil
		}
	}
}

func (p *XMLPullParser) Attribute(name string) string {
	for _, attr := range p.Attrs {
		if attr.Name.Local == name {
			return attr.Value
		}
	}
	return ""
}

func (p *XMLPullParser) Expect(event XMLEventType, name string) (err error) {
	return p.ExpectAll(event, "*", name)
}

func (p *XMLPullParser) ExpectAll(event XMLEventType, space string, name string) (err error) {
	if !(p.Event == event && (p.Space == space || space == "*") && (p.Name == name || name == "*")) {
		err = fmt.Errorf("Expected Space:%s Name:%s Event:%s but got Space:%s Name:%s Event:%s", space, name, p.eventName(event), p.Space, p.Name, p.eventName(p.Event))
	}
	return
}

func (p *XMLPullParser) processToken(t xml.Token) {
	switch tt := t.(type) {
	case xml.StartElement:
		p.processStartToken(tt)
	case xml.EndElement:
		p.processEndToken(tt)
	case xml.CharData:
		p.processCharDataToken(tt)
	case xml.Comment:
		p.processCommentToken(tt)
	case xml.ProcInst:
		p.processProcInstToken(tt)
	case xml.Directive:
		p.processDirectiveToken(tt)
	}
}

func (p *XMLPullParser) processStartToken(t xml.StartElement) {
	p.Depth++
	p.Attrs = t.Attr
	p.Name = t.Name.Local
	p.Space = t.Name.Space
}

func (p *XMLPullParser) processEndToken(t xml.EndElement) {
	p.Depth--
	p.Name = t.Name.Local
}

func (p *XMLPullParser) processCharDataToken(t xml.CharData) {
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) processCommentToken(t xml.Comment) {
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) processProcInstToken(t xml.ProcInst) {
	p.Event = ProcessingInstruction
	p.Text = fmt.Sprintf("%s %s", t.Target, string(t.Inst))
}

func (p *XMLPullParser) processDirectiveToken(t xml.Directive) {
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) resetTokenState() {
	p.Attrs = nil
	p.Name = ""
	p.Space = ""
	p.Text = ""
}

func (p *XMLPullParser) isWhitespace() bool {
	return strings.TrimSpace(p.Text) == ""
}

func (p *XMLPullParser) eventName(e XMLEventType) (name string) {
	switch e {
	case StartTag:
		name = "StartTag"
	case EndTag:
		name = "EndTag"
	case ProcessingInstruction:
		name = "ProcessingInstruction"
	case Directive:
		name = "Directive"
	case Comment:
		name = "Comment"
	case Text:
		name = "Text"
	case IgnorableWhitespace:
		name = "IgnorableWhitespace"
	}
	return
}

func (p *XMLPullParser) eventType(t xml.Token) (event XMLEventType) {
	switch t.(type) {
	case xml.StartElement:
		event = StartTag
	case xml.EndElement:
		event = EndTag
	case xml.CharData:
		event = Text
	case xml.Comment:
		event = Comment
	case xml.ProcInst:
		event = ProcessingInstruction
	case xml.Directive:
		event = Directive
	}
	return
}
<commit_msg>Add 1 token peeking, coalesce text events in Next and remove ignorable whitespace for now<commit_after>package xpp

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"strings"
)

type XMLEventType int

const (
	StartDocument XMLEventType = iota
	EndDocument
	StartTag
	EndTag
	Text
	Comment
	ProcessingInstruction
	Directive
	IgnorableWhitespace // TODO: ?
	// TODO: CDSECT ?
)

type XMLPullParser struct {
	Depth int
	Event XMLEventType
	Attrs []xml.Attr
	Name  string
	Space string
	Text  string

	decoder   *xml.Decoder
	token     interface{}
	peekToken interface{}
	peekEvent XMLEventType
	peekErr   error
}

func NewXMLPullParser(r io.Reader) *XMLPullParser {
	d := xml.NewDecoder(r)
	d.Strict = false
	return &XMLPullParser{
		decoder: d,
		Event:   StartDocument,
		Depth:   0,
	}
}

func (p *XMLPullParser) NextTag() (event XMLEventType, err error) {
	t, err := p.Next()
	if err != nil {
		return event, err
	}

	if t == Text && p.isWhitespace() {
		t, err = p.Next()
		if err != nil {
			return event, err
		}
	}

	if t != StartTag && t != EndTag {
		return event, fmt.Errorf("Expected StartTag or EndTag but got %s", p.eventName(t))
	}

	return t, nil
}

func (p *XMLPullParser) Next() (event XMLEventType, err error) {
	text := ""

	for {
		event, err = p.NextToken()
		if err != nil {
			return event, err
		}

		// Return immediately after encountering a StartTag
		// EndTag or EndDocument
		if event == StartTag ||
			event == EndTag ||
			event == EndDocument {
			return event, nil
		}

		if event == Comment ||
			event == Directive ||
			event == ProcessingInstruction {
			text = ""
			continue
		}

		// Coalesce text event value
		if event == Text {
			text += p.Text
		}

		// Return the text event if it is going to be
		// ended by a Start/EndTag or EndDocument.
		// Otherwise we will continue to coalesce text
		// events.
		if text != "" && (p.peekEvent == StartTag ||
			p.peekEvent == EndTag ||
			p.peekEvent == EndDocument) {
			p.Text = text
			return Text, nil
		}
	}
	return event, nil
}

func (p *XMLPullParser) NextToken() (event XMLEventType, err error) {
	// Clear any state held for the previous token
	p.resetTokenState()

	if p.peekErr != nil {
		return event, p.peekErr
	}

	if p.Event == StartDocument {
		// Preload the peek token when first starting
		p.peekNextToken()
	} else if p.Event == EndDocument {
		// Always return EndDocument once that state has
		// been reached.
		return p.Event, nil
	}

	// Switch peek token/event to the current token/event
	p.Event = p.peekEvent
	p.token = p.peekToken
	p.processToken(p.token)

	p.peekNextToken()

	// Return current event (previously the peek token)
	return p.Event, nil
}

func (p *XMLPullParser) peekNextToken() {
	// Peek the next token/event
	peekToken, err := p.decoder.Token()
	if err != nil {
		if err == io.EOF {
			// XML decoder returns the EOF as an error
			// but we want to return it as a valid
			// EndDocument token instead
			p.peekToken = nil
			p.peekEvent = EndDocument
		} else {
			p.peekErr = err
		}
		return
	}
	p.peekToken = xml.CopyToken(peekToken)
	p.peekEvent = p.eventType(peekToken)
}

func (p *XMLPullParser) NextText() (string, error) {
	if p.Event != StartTag {
		return "", errors.New("Parser must be on StartTag to get NextText()")
	}

	t, err := p.Next()
	if err != nil {
		return "", err
	}

	if t == Text {
		result := p.Text
		nt, err := p.Next()
		if err != nil {
			return "", err
		}

		if nt != EndTag {
			return "", errors.New("Event Text must be immediately followed by EndTag")
		}

		return result, nil
	} else if t == EndTag {
		return "", nil
	} else {
		return "", errors.New("Parser must be on StartTag or Text to read text")
	}
}

func (p *XMLPullParser) Skip() error {
	for {
		tok, err := p.NextToken()
		if err != nil {
			return err
		}
		if tok == StartTag {
			if err := p.Skip(); err != nil {
				return err
			}
		} else if tok == EndTag {
			return nil
		}
	}
}

func (p *XMLPullParser) Attribute(name string) string {
	for _, attr := range p.Attrs {
		if attr.Name.Local == name {
			return attr.Value
		}
	}
	return ""
}

func (p *XMLPullParser) Expect(event XMLEventType, name string) (err error) {
	return p.ExpectAll(event, "*", name)
}

func (p *XMLPullParser) ExpectAll(event XMLEventType, space string, name string) (err error) {
	if !(p.Event == event && (p.Space == space || space == "*") && (p.Name == name || name == "*")) {
		err = fmt.Errorf("Expected Space:%s Name:%s Event:%s but got Space:%s Name:%s Event:%s", space, name, p.eventName(event), p.Space, p.Name, p.eventName(p.Event))
	}
	return
}

func (p *XMLPullParser) processToken(t xml.Token) {
	switch tt := t.(type) {
	case xml.StartElement:
		p.processStartToken(tt)
	case xml.EndElement:
		p.processEndToken(tt)
	case xml.CharData:
		p.processCharDataToken(tt)
	case xml.Comment:
		p.processCommentToken(tt)
	case xml.ProcInst:
		p.processProcInstToken(tt)
	case xml.Directive:
		p.processDirectiveToken(tt)
	}
}

func (p *XMLPullParser) processStartToken(t xml.StartElement) {
	p.Depth++
	p.Attrs = t.Attr
	p.Name = t.Name.Local
	p.Space = t.Name.Space
}

func (p *XMLPullParser) processEndToken(t xml.EndElement) {
	p.Depth--
	p.Name = t.Name.Local
}

func (p *XMLPullParser) processCharDataToken(t xml.CharData) {
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) processCommentToken(t xml.Comment) {
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) processProcInstToken(t xml.ProcInst) {
	p.Text = fmt.Sprintf("%s %s", t.Target, string(t.Inst))
}

func (p *XMLPullParser) processDirectiveToken(t xml.Directive) {
	p.Text = string([]byte(t))
}

func (p *XMLPullParser) resetTokenState() {
	p.Attrs = nil
	p.Name = ""
	p.Space = ""
	p.Text = ""
}

func (p *XMLPullParser) isWhitespace() bool {
	return strings.TrimSpace(p.Text) == ""
}

func (p *XMLPullParser) eventName(e XMLEventType) (name string) {
	switch e {
	case StartTag:
		name = "StartTag"
	case EndTag:
		name = "EndTag"
	case StartDocument:
		name = "StartDocument"
	case EndDocument:
		name = "EndDocument"
	case ProcessingInstruction:
		name = "ProcessingInstruction"
	case Directive:
		name = "Directive"
	case Comment:
		name = "Comment"
	case Text:
		name = "Text"
	case IgnorableWhitespace:
		name = "IgnorableWhitespace"
	}
	return
}

func (p *XMLPullParser) eventType(t xml.Token) (event XMLEventType) {
	switch t.(type) {
	case xml.StartElement:
		event = StartTag
	case xml.EndElement:
		event = EndTag
	case xml.CharData:
		event = Text
	case xml.Comment:
		event = Comment
	case xml.ProcInst:
		event = ProcessingInstruction
	case xml.Directive:
		event = Directive
	}
	return
}
<|endoftext|>


<commit_before>package zmq

import (
	"bufio"
	"encoding/binary"
	"io"
	"net"
	"os"
)

const (
	SOCK_PAIR = iota
	SOCK_PUB
	SOCK_SUB
	SOCK_REQ
	SOCK_REP
	//SOCK_XREQ
	//SOCK_XREP
	SOCK_PULL
	SOCK_PUSH
)

type binder interface {
	bind(rwc io.ReadWriteCloser)
}

type nilBinder struct {}

func (b nilBinder) bind(rwc io.ReadWriteCloser) {}

type frameReader interface {
	binder
	ReadFrame([]byte) ([]byte, os.Error)
}

type bindWriter interface {
	binder
	io.Writer
}

type Socket struct {
	identity string
	r frameReader
	w bindWriter
}

func NewSocket(typ int, identity string) (*Socket, os.Error) {
	var r frameReader
	var w bindWriter
	switch typ {
	case SOCK_PAIR:
	case SOCK_PUB:
		mw := make(multiWriter, 0, 5)
		w = newFrameWriter(mw)
	case SOCK_SUB:
	case SOCK_REQ:
	case SOCK_REP:
	case SOCK_PULL:
		r = newQueuedReader()
	case SOCK_PUSH:
		w = newLbWriter()
	default:
	}
	return &Socket{identity, r, w}, nil
}

func (s *Socket) ReadFrame(body []byte) ([]byte, os.Error) {
	if s.r == nil {
		return body, os.NewError("socket is not readable")
	}
	return s.r.ReadFrame(body)
}

func (s *Socket) Write(b []byte) (int, os.Error) {
	if s.w == nil {
		return 0, os.NewError("socket is not writable")
	}
	return s.w.Write(b)
}

func (s *Socket) Bind(network, addr string) os.Error {
	conn, err := net.Dial(network, addr)
	if err != nil {
		return err
	}
	// TODO: avoid making extra frameWriters and frameReaders
	if s.w != nil {
		fw := newFrameWriter(conn)
		// TODO: write identity properly
		b := make([]byte, len(s.identity)+2)
		b[0] = byte(len(s.identity))
		b[1] = 0
		copy(b[2:], s.identity)
		fw.Write(b)
		fc := newFrameReader(conn)
		fc.ReadFrame(nil)
		s.w.bind(conn)
	}
	if s.r != nil {
		fw := newFrameWriter(conn)
		fw.Write(nil)
		fc := newFrameReader(conn)
		fc.ReadFrame(nil)
		s.r.bind(conn)
	}
	return nil
}

// Similar to io.MultiWriter, but we have access to its internals and it has a Close method.
type multiWriter []io.WriteCloser

func (mw multiWriter) Write(p []byte) (n int, err os.Error) {
	n = len(p)
	for _, w := range mw {
		n2, err2 := w.Write(p)
		if err2 != nil {
			n = n2
			err = err2
		}
	}
	return
}

func (mw multiWriter) Close() (err os.Error) {
	for _, w := range mw {
		err2 := w.Close()
		if err2 != nil {
			err = err2
		}
	}
	return
}

func (mw multiWriter) bind(rwc io.ReadWriteCloser) {
	mw = append(mw, rwc)
}

// A load-balanced WriteCloser
type lbWriter struct {
	w []io.WriteCloser
	c chan []byte
}

func newLbWriter() *lbWriter {
	c := make(chan []byte, 10)
	return &lbWriter{nil, c}
}

func (w *lbWriter) bind(rwc io.ReadWriteCloser) {
	go writeListen(rwc, w.c)
	// TODO: figure out a better way to keep track of writers
	w.w = append(w.w, rwc)
}

func writeListen(w io.WriteCloser, c chan []byte) {
	for {
		b, ok := <-c
		if !ok {
			w.Close()
			break
		}
		if _, err := w.Write(b); err != nil {
			// pass it on to a different writer
			c <- b
			break
		}
	}
}

func (w *lbWriter) Write(b []byte) (int, os.Error) {
	w.c <- b
	// TODO: can we do better?
	return len(b), nil
}

func (w *lbWriter) Close() os.Error {
	close(w.c)
	return nil
}

type queuedReader struct {
	// TODO: change to ReadCloser
	r []io.ReadWriteCloser
	c chan []byte
}

func newQueuedReader() *queuedReader {
	c := make(chan []byte, 10)
	return &queuedReader{nil, c}
}

func (r *queuedReader) bind(rwc io.ReadWriteCloser) {
	fr := newFrameReader(rwc)
	go readListen(fr, r.c)
	// TODO: figure out a better way to keep track of readers
	r.r = append(r.r, rwc)
}

func readListen(fr *defFrameReader, c chan []byte) {
	for {
		// TODO: stop the allocation!
		b, err := fr.ReadFrame(nil)
		if err != nil {
			break
		}
		c <- b
	}
}

func (r *queuedReader) ReadFrame(body []byte) ([]byte, os.Error) {
	b := <-r.c
	return b, nil
}

func (r *queuedReader) Close() os.Error {
	for _, r := range r.r {
		r.Close()
	}
	return nil
}

type frameWriter struct {
	nilBinder
	wc io.WriteCloser
	buf *bufio.Writer
}

type defFrameReader struct {
	rc io.ReadCloser
	buf *bufio.Reader
}

func newFrameWriter(wc io.WriteCloser) *frameWriter {
	w := &frameWriter{wc: wc, buf: bufio.NewWriter(wc)}
	return w
}

func newFrameReader(rc io.ReadCloser) *defFrameReader {
	r := &defFrameReader{rc, bufio.NewReader(rc)}
	return r
}

func (fc *frameWriter) Write(b []byte) (n int, err os.Error) {
	// + 1 for flags
	l := len(b) + 1
	if l < 255 {
		n, err = fc.buf.Write([]byte{byte(l)})
	} else {
		var length [9]byte
		length[0] = 255
		binary.BigEndian.PutUint64(length[1:], uint64(l))
		n, err = fc.buf.Write(length[:])
	}
	if err != nil {
		return
	}
	// flags; it’s impossible to have a slice with len > 2^64-1, so the MORE flag is always 0
	// All other flag bits are reserved.
	nn, err := fc.buf.Write([]byte{0})
	n += nn
	if err != nil {
		return
	}
	nn, err = fc.buf.Write(b)
	n += nn
	fc.buf.Flush()
	return
}

func (fc *frameWriter) Close() os.Error {
	return fc.wc.Close()
}

func (fc *defFrameReader) ReadFrame(body []byte) ([]byte, os.Error) {
	var length uint64
	var b [8]byte
	if _, err := fc.buf.Read(b[:1]); err != nil {
		return nil, err
	}
	if b[0] == 255 {
		if _, err := fc.buf.Read(b[:]); err != nil {
			return nil, err
		}
		length = binary.BigEndian.Uint64(b[:])
	} else {
		length = uint64(b[0])
	}
	if uint64(len(body)) < length {
		body = make([]byte, length)
	}
	if _, err := fc.buf.Read(body); err != nil {
		return nil, err
	}
	if body[0]&1 != 0 {
		panic("can't handle MORE")
	}
	return body[1:], nil
}

func (fc *defFrameReader) Close() os.Error {
	return fc.rc.Close()
}
<commit_msg>Shuffle frame writer and reader, remove an allocation<commit_after>package zmq

import (
	"bufio"
	"encoding/binary"
	"io"
	"net"
	"os"
)

const (
	SOCK_PAIR = iota
	SOCK_PUB
	SOCK_SUB
	SOCK_REQ
	SOCK_REP
	//SOCK_XREQ
	//SOCK_XREP
	SOCK_PULL
	SOCK_PUSH
)

type nilWBinder struct {}

func (b nilWBinder) bind(wc io.WriteCloser) {}

type nilRBinder struct {}

func (b nilRBinder) bind(fr *defFrameReader) {}

type frameReader interface {
	bind(fr *defFrameReader)
	ReadFrame([]byte) ([]byte, os.Error)
}

type bindWriter interface {
	io.Writer
	bind(wc io.WriteCloser)
}

type Socket struct {
	identity string
	r frameReader
	w bindWriter
}

func NewSocket(typ int, identity string) (*Socket, os.Error) {
	var r frameReader
	var w bindWriter
	switch typ {
	case SOCK_PAIR:
	case SOCK_PUB:
		mw := make(multiWriter, 0, 5)
		w = newFrameWriter(mw)
	case SOCK_SUB:
	case SOCK_REQ:
	case SOCK_REP:
	case SOCK_PULL:
		r = newQueuedReader()
	case SOCK_PUSH:
		w = newLbWriter()
	default:
	}
	return &Socket{identity, r, w}, nil
}

func (s *Socket) ReadFrame(body []byte) ([]byte, os.Error) {
	if s.r == nil {
		return body, os.NewError("socket is not readable")
	}
	return s.r.ReadFrame(body)
}

func (s *Socket) Write(b []byte) (int, os.Error) {
	if s.w == nil {
		return 0, os.NewError("socket is not writable")
	}
	return s.w.Write(b)
}

func (s *Socket) Bind(network, addr string) os.Error {
	conn, err := net.Dial(network, addr)
	if err != nil {
		return err
	}
	// TODO: avoid making extra frameWriters and frameReaders
	if s.w != nil {
		fw := newFrameWriter(conn)
		// TODO: write identity properly
		b := make([]byte, len(s.identity)+2)
		b[0] = byte(len(s.identity))
		b[1] = 0
		copy(b[2:], s.identity)
		fw.Write(b)
		fr := newFrameReader(conn)
		fr.ReadFrame(nil)
		s.w.bind(conn)
	}
	if s.r != nil {
		fw := newFrameWriter(conn)
		fw.Write(nil)
		fr := newFrameReader(conn)
		fr.ReadFrame(nil)
		s.r.bind(fr)
	}
	return nil
}

// Similar to io.MultiWriter, but we have access to its internals and it has a Close method.
type multiWriter []io.WriteCloser

func (mw multiWriter) Write(p []byte) (n int, err os.Error) {
	n = len(p)
	for _, w := range mw {
		n2, err2 := w.Write(p)
		if err2 != nil {
			n = n2
			err = err2
		}
	}
	return
}

func (mw multiWriter) Close() (err os.Error) {
	for _, w := range mw {
		err2 := w.Close()
		if err2 != nil {
			err = err2
		}
	}
	return
}

func (mw multiWriter) bind(wc io.WriteCloser) {
	mw = append(mw, wc)
}

// A load-balanced WriteCloser
type lbWriter struct {
	w []io.WriteCloser
	c chan []byte
}

func newLbWriter() *lbWriter {
	c := make(chan []byte, 10)
	return &lbWriter{nil, c}
}

func (w *lbWriter) bind(wc io.WriteCloser) {
	go writeListen(wc, w.c)
	// TODO: figure out a better way to keep track of writers
	w.w = append(w.w, wc)
}

func writeListen(w io.WriteCloser, c chan []byte) {
	for {
		b, ok := <-c
		if !ok {
			w.Close()
			break
		}
		if _, err := w.Write(b); err != nil {
			// pass it on to a different writer
			c <- b
			break
		}
	}
}

func (w *lbWriter) Write(b []byte) (int, os.Error) {
	w.c <- b
	// TODO: can we do better?
	return len(b), nil
}

func (w *lbWriter) Close() os.Error {
	close(w.c)
	return nil
}

type queuedReader struct {
	fr []*defFrameReader
	c chan []byte
}

func newQueuedReader() *queuedReader {
	c := make(chan []byte, 10)
	return &queuedReader{nil, c}
}

func (r *queuedReader) bind(fr *defFrameReader) {
	go readListen(fr, r.c)
	// TODO: figure out a better way to keep track of readers
	r.fr = append(r.fr, fr)
}

func readListen(fr *defFrameReader, c chan []byte) {
	for {
		// TODO: stop the allocation!
		b, err := fr.ReadFrame(nil)
		if err != nil {
			break
		}
		c <- b
	}
}

func (r *queuedReader) ReadFrame(body []byte) ([]byte, os.Error) {
	b := <-r.c
	return b, nil
}

func (r *queuedReader) Close() os.Error {
	for _, r := range r.fr {
		r.Close()
	}
	return nil
}

type frameWriter struct {
	nilWBinder
	wc io.WriteCloser
	buf *bufio.Writer
}

func newFrameWriter(wc io.WriteCloser) *frameWriter {
	w := &frameWriter{wc: wc, buf: bufio.NewWriter(wc)}
	return w
}

func (fc *frameWriter) Write(b []byte) (n int, err os.Error) {
	// + 1 for flags
	l := len(b) + 1
	if l < 255 {
		n, err = fc.buf.Write([]byte{byte(l)})
	} else {
		var length [9]byte
		length[0] = 255
		binary.BigEndian.PutUint64(length[1:], uint64(l))
		n, err = fc.buf.Write(length[:])
	}
	if err != nil {
		return
	}
	// flags; it’s impossible to have a slice with len > 2^64-1, so the MORE flag is always 0
	// All other flag bits are reserved.
	nn, err := fc.buf.Write([]byte{0})
	n += nn
	if err != nil {
		return
	}
	nn, err = fc.buf.Write(b)
	n += nn
	fc.buf.Flush()
	return
}

func (fc *frameWriter) Close() os.Error {
	return fc.wc.Close()
}

type defFrameReader struct {
	nilRBinder
	rc io.ReadCloser
	buf *bufio.Reader
}

func newFrameReader(rc io.ReadCloser) *defFrameReader {
	r := &defFrameReader{rc: rc, buf: bufio.NewReader(rc)}
	return r
}

func (fr *defFrameReader) ReadFrame(body []byte) ([]byte, os.Error) {
	var length uint64
	var b [8]byte
	if _, err := fr.buf.Read(b[:1]); err != nil {
		return nil, err
	}
	if b[0] == 255 {
		if _, err := fr.buf.Read(b[:]); err != nil {
			return nil, err
		}
		length = binary.BigEndian.Uint64(b[:])
	} else {
		length = uint64(b[0])
	}
	if uint64(len(body)) < length {
		body = make([]byte, length)
	}
	if _, err := fr.buf.Read(body); err != nil {
		return nil, err
	}
	if body[0]&1 != 0 {
		panic("can't handle MORE")
	}
	return body[1:], nil
}

func (fr *defFrameReader) Close() os.Error {
	return fr.rc.Close()
}
<|endoftext|>


<commit_before>// Copyright 2017 The appc Authors
//
// 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 common

import (
	"testing"
)

func TestMediaTypeSet(t *testing.T) {
	tests := []struct {
		ms                    MediaTypeSet
		expectedManifestTypes []string
		expectedConfigTypes   []string
		expectedLayerTypes    []string
	}{
		{
			MediaTypeSet{MediaTypeOptionDockerV21},
			[]string{MediaTypeDockerV21Manifest},
			[]string{},
			[]string{},
		},
		{
			MediaTypeSet{MediaTypeOptionDockerV22},
			[]string{MediaTypeDockerV22Manifest},
			[]string{MediaTypeDockerV22Config},
			[]string{MediaTypeDockerV22RootFS},
		},
		{
			MediaTypeSet{MediaTypeOptionOCIV1Pre},
			[]string{MediaTypeOCIV1Manifest},
			[]string{MediaTypeOCIV1Config},
			[]string{MediaTypeOCIV1Layer},
		},
		{
			MediaTypeSet{},
			[]string{MediaTypeDockerV21Manifest, MediaTypeDockerV22Manifest, MediaTypeOCIV1Manifest},
			[]string{MediaTypeDockerV22Config, MediaTypeOCIV1Config},
			[]string{MediaTypeDockerV22RootFS, MediaTypeOCIV1Layer},
		},
		{
			MediaTypeSet{MediaTypeOptionDockerV21, MediaTypeOptionDockerV22, MediaTypeOptionOCIV1Pre},
			[]string{MediaTypeDockerV21Manifest, MediaTypeDockerV22Manifest, MediaTypeOCIV1Manifest},
			[]string{MediaTypeDockerV22Config, MediaTypeOCIV1Config},
			[]string{MediaTypeDockerV22RootFS, MediaTypeOCIV1Layer},
		},
		{
			MediaTypeSet{MediaTypeOptionDockerV21, MediaTypeOptionOCIV1Pre},
			[]string{MediaTypeDockerV21Manifest, MediaTypeOCIV1Manifest},
			[]string{MediaTypeOCIV1Config},
			[]string{MediaTypeOCIV1Layer},
		},
	}

	for _, test := range tests {
		if !isEqual(test.expectedManifestTypes, test.ms.ManifestMediaTypes()) {
			t.Errorf("expected manifest media types didn't match what was returned:\n%v\n%v", test.expectedManifestTypes, test.ms.ManifestMediaTypes())
		}
		if !isEqual(test.expectedConfigTypes, test.ms.ConfigMediaTypes()) {
			t.Errorf("expected config media types didn't match what was returned:\n%v\n%v", test.expectedConfigTypes, test.ms.ConfigMediaTypes())
		}
		if !isEqual(test.expectedLayerTypes, test.ms.LayerMediaTypes()) {
			t.Errorf("expected layer media types didn't match what was returned:\n%v\n%v", test.expectedLayerTypes, test.ms.LayerMediaTypes())
		}
	}
}

func TestRegistryOptionSet(t *testing.T) {
	tests := []struct {
		rs       RegistryOptionSet
		allowsV1 bool
		allowsV2 bool
	}{
		{
			RegistryOptionSet{RegistryOptionV1}, true, false,
		},
		{
			RegistryOptionSet{RegistryOptionV2}, false, true,
		},
		{
			RegistryOptionSet{RegistryOptionV1, RegistryOptionV2}, true, true,
		},
		{
			RegistryOptionSet{}, true, true,
		},
	}
	for _, test := range tests {
		if test.allowsV1 != test.rs.AllowsV1() {
			t.Errorf("doesn't allow V1 when it should")
		}
		if test.allowsV2 != test.rs.AllowsV2() {
			t.Errorf("doesn't allow V1 when it should")
		}
	}
}

func isEqual(val1, val2 []string) bool {
	if len(val1) != len(val2) {
		return false
	}
loop1:
	for _, thing1 := range val1 {
		for _, thing2 := range val2 {
			if thing1 == thing2 {
				continue loop1
			}
		}
		return false
	}
	return true
}
<commit_msg>lib/common: unit test `ParseDockerURL`<commit_after>// Copyright 2017 The appc Authors
//
// 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 common

import (
	_ "crypto/sha256"
	"reflect"
	"testing"
)

func TestMediaTypeSet(t *testing.T) {
	tests := []struct {
		ms                    MediaTypeSet
		expectedManifestTypes []string
		expectedConfigTypes   []string
		expectedLayerTypes    []string
	}{
		{
			MediaTypeSet{MediaTypeOptionDockerV21},
			[]string{MediaTypeDockerV21Manifest},
			[]string{},
			[]string{},
		},
		{
			MediaTypeSet{MediaTypeOptionDockerV22},
			[]string{MediaTypeDockerV22Manifest},
			[]string{MediaTypeDockerV22Config},
			[]string{MediaTypeDockerV22RootFS},
		},
		{
			MediaTypeSet{MediaTypeOptionOCIV1Pre},
			[]string{MediaTypeOCIV1Manifest},
			[]string{MediaTypeOCIV1Config},
			[]string{MediaTypeOCIV1Layer},
		},
		{
			MediaTypeSet{},
			[]string{MediaTypeDockerV21Manifest, MediaTypeDockerV22Manifest, MediaTypeOCIV1Manifest},
			[]string{MediaTypeDockerV22Config, MediaTypeOCIV1Config},
			[]string{MediaTypeDockerV22RootFS, MediaTypeOCIV1Layer},
		},
		{
			MediaTypeSet{MediaTypeOptionDockerV21, MediaTypeOptionDockerV22, MediaTypeOptionOCIV1Pre},
			[]string{MediaTypeDockerV21Manifest, MediaTypeDockerV22Manifest, MediaTypeOCIV1Manifest},
			[]string{MediaTypeDockerV22Config, MediaTypeOCIV1Config},
			[]string{MediaTypeDockerV22RootFS, MediaTypeOCIV1Layer},
		},
		{
			MediaTypeSet{MediaTypeOptionDockerV21, MediaTypeOptionOCIV1Pre},
			[]string{MediaTypeDockerV21Manifest, MediaTypeOCIV1Manifest},
			[]string{MediaTypeOCIV1Config},
			[]string{MediaTypeOCIV1Layer},
		},
	}

	for _, test := range tests {
		if !isEqual(test.expectedManifestTypes, test.ms.ManifestMediaTypes()) {
			t.Errorf("expected manifest media types didn't match what was returned:\n%v\n%v", test.expectedManifestTypes, test.ms.ManifestMediaTypes())
		}
		if !isEqual(test.expectedConfigTypes, test.ms.ConfigMediaTypes()) {
			t.Errorf("expected config media types didn't match what was returned:\n%v\n%v", test.expectedConfigTypes, test.ms.ConfigMediaTypes())
		}
		if !isEqual(test.expectedLayerTypes, test.ms.LayerMediaTypes()) {
			t.Errorf("expected layer media types didn't match what was returned:\n%v\n%v", test.expectedLayerTypes, test.ms.LayerMediaTypes())
		}
	}
}

func TestRegistryOptionSet(t *testing.T) {
	tests := []struct {
		rs       RegistryOptionSet
		allowsV1 bool
		allowsV2 bool
	}{
		{
			RegistryOptionSet{RegistryOptionV1}, true, false,
		},
		{
			RegistryOptionSet{RegistryOptionV2}, false, true,
		},
		{
			RegistryOptionSet{RegistryOptionV1, RegistryOptionV2}, true, true,
		},
		{
			RegistryOptionSet{}, true, true,
		},
	}
	for _, test := range tests {
		if test.allowsV1 != test.rs.AllowsV1() {
			t.Errorf("doesn't allow V1 when it should")
		}
		if test.allowsV2 != test.rs.AllowsV2() {
			t.Errorf("doesn't allow V1 when it should")
		}
	}
}

func isEqual(val1, val2 []string) bool {
	if len(val1) != len(val2) {
		return false
	}
loop1:
	for _, thing1 := range val1 {
		for _, thing2 := range val2 {
			if thing1 == thing2 {
				continue loop1
			}
		}
		return false
	}
	return true
}

func TestParseDockerURL(t *testing.T) {
	tests := []struct {
		input    string
		expected *ParsedDockerURL
	}{
		{
			"busybox",
			&ParsedDockerURL{
				OriginalName: "busybox",
				IndexURL:     "registry-1.docker.io",
				ImageName:    "library/busybox",
				Tag:          "latest",
				Digest:       "",
			},
		},
		{
			"library/busybox",
			&ParsedDockerURL{
				OriginalName: "library/busybox",
				IndexURL:     "registry-1.docker.io",
				ImageName:    "library/busybox",
				Tag:          "latest",
				Digest:       "",
			},
		},
		{
			"docker.io/library/busybox:1",
			&ParsedDockerURL{
				OriginalName: "docker.io/library/busybox:1",
				IndexURL:     "registry-1.docker.io",
				ImageName:    "library/busybox",
				Tag:          "1",
				Digest:       "",
			},
		},
		{
			"docker.io/library/busybox",
			&ParsedDockerURL{
				OriginalName: "docker.io/library/busybox",
				IndexURL:     "registry-1.docker.io",
				ImageName:    "library/busybox",
				Tag:          "latest",
				Digest:       "",
			},
		},
		{
			"gcr.io/google-samples/node-hello:1.0",
			&ParsedDockerURL{
				OriginalName: "gcr.io/google-samples/node-hello:1.0",
				IndexURL:     "gcr.io",
				ImageName:    "google-samples/node-hello",
				Tag:          "1.0",
				Digest:       "",
			},
		},
		{
			"alpine@sha256:ea0d1389812f43e474c50155ec4914e1b48792d420820c15cab28c0794034950",
			&ParsedDockerURL{
				OriginalName: "alpine@sha256:ea0d1389812f43e474c50155ec4914e1b48792d420820c15cab28c0794034950",
				IndexURL:     "registry-1.docker.io",
				ImageName:    "library/alpine",
				Tag:          "",
				Digest:       "sha256:ea0d1389812f43e474c50155ec4914e1b48792d420820c15cab28c0794034950",
			},
		},
	}
	for _, test := range tests {
		parsed, err := ParseDockerURL(test.input)
		if err != nil && test.expected != nil {
			t.Errorf("error when parsing %q: %v\nexpected: %+v", test.input, err, test.expected)
		} else if err == nil && test.expected == nil {
			t.Errorf("expected %q to result in error\n", test.input)
		} else if !reflect.DeepEqual(test.expected, parsed) {
			t.Errorf("expected and parsed `&ParsedDockerURL{}` differ:\nexpected: %+v\nparsed:   %+v\n", test.expected, parsed)
		}
	}
}
<|endoftext|>


<commit_before>package event

import ()

const (
	CLIENT_REGISTRATION = "CR" //client registered (for the first time)
	CLIENT_AUTO_REREGI  = "CA" //client automatically re-registered
	CLIENT_UNREGISTER   = "CU" //client unregistered
	WORK_CHECKOUT       = "WC" //workunit checkout
	WORK_FAIL           = "WF" //workunit fails running
	//server only events
	SERVER_START   = "SS" //awe-server start
	SERVER_RECOVER = "SR" //awe-server start with recover option  (-recover)
	JOB_SUBMISSION = "JQ" //job submitted
	TASK_ENQUEUE   = "TQ" //task parsed and enqueue
	WORK_DONE      = "WD" //workunit received successful feedback from client
	WORK_REQUEUE   = "WR" //workunit requeue after receive failed feedback from client
	WORK_SUSPEND   = "WP" //workunit suspend after failing for conf.Max_Failure times
	TASK_DONE      = "TD" //task done (all the workunits in the task have finished)
	TASK_SKIPPED   = "TS" //task skipped (skip option > 0)
	JOB_DONE       = "JD" //job done (all the tasks in the job have finished)
	JOB_SUSPEND    = "JP" //job suspended
	JOB_DELETED    = "JL" //job deleted
	//client only events
	WORK_START   = "WS" //workunit command start running
	WORK_END     = "WE" //workunit command finish running
	WORK_RETURN  = "WR" //send back failed workunit to server
	WORK_DISCARD = "WI" //workunit discarded after receiving discard signal from server
	FILE_IN      = "FI" //start fetching input file from shock
	FILE_READY   = "FR" //finish fetching input file from shock
	FILE_OUT     = "FO" //start pushing output file to shock
	FILE_DONE    = "FD" //finish pushing output file to shock
	//proxy only events
	WORK_QUEUED = "WQ" //workunit queued at proxy
)
<commit_msg>add code for attribute retrieval in events<commit_after>package event

import ()

const (
	CLIENT_REGISTRATION = "CR" //client registered (for the first time)
	CLIENT_AUTO_REREGI  = "CA" //client automatically re-registered
	CLIENT_UNREGISTER   = "CU" //client unregistered
	WORK_CHECKOUT       = "WC" //workunit checkout
	WORK_FAIL           = "WF" //workunit fails running
	//server only events
	SERVER_START   = "SS" //awe-server start
	SERVER_RECOVER = "SR" //awe-server start with recover option  (-recover)
	JOB_SUBMISSION = "JQ" //job submitted
	TASK_ENQUEUE   = "TQ" //task parsed and enqueue
	WORK_DONE      = "WD" //workunit received successful feedback from client
	WORK_REQUEUE   = "WR" //workunit requeue after receive failed feedback from client
	WORK_SUSPEND   = "WP" //workunit suspend after failing for conf.Max_Failure times
	TASK_DONE      = "TD" //task done (all the workunits in the task have finished)
	TASK_SKIPPED   = "TS" //task skipped (skip option > 0)
	JOB_DONE       = "JD" //job done (all the tasks in the job have finished)
	JOB_SUSPEND    = "JP" //job suspended
	JOB_DELETED    = "JL" //job deleted
	//client only events
	WORK_START   = "WS" //workunit command start running
	WORK_END     = "WE" //workunit command finish running
	WORK_RETURN  = "WR" //send back failed workunit to server
	WORK_DISCARD = "WI" //workunit discarded after receiving discard signal from server
	FILE_IN      = "FI" //start fetching input file from shock
	FILE_READY   = "FR" //finish fetching input file from shock
	FILE_OUT     = "FO" //start pushing output file to shock
	FILE_DONE    = "FD" //finish pushing output file to shock
	ATTR_IN      = "AI" //start fetching input attributes from shock
	ATTR_READY   = "AR" //finish fetching input attributes from shock
	//proxy only events
	WORK_QUEUED = "WQ" //workunit queued at proxy
)
<|endoftext|>


<commit_before>package logberry

import (
	"sync/atomic"
)

// Task represents a particular component, function, or activity.  In
// general a Task is meant to be used within a single thread of
// execution, and the calling code is responsible for managing any
// concurrent manipulation.
type Task struct {
	uid uint64

	root *Root

	parent *Task

	component string

	activity string

	data D
}

var numtasks uint64

func newtaskuid() uint64 {
	// We have seen this atomic call cause problems on ARM...
	return atomic.AddUint64(&numtasks, 1) - 1
}

func newtask(parent *Task, component string, activity string, data []interface{}) *Task {

	t := &Task{
		uid:    newtaskuid(),
		parent: parent,
		activity: activity,
		data: DAggregate(data),
	}

	if parent != nil {
		t.root = parent.root
		t.component = parent.component
	} else {
		t.root = Std
	}

	if component != "" {
		t.component = component
	}

	t.root.event(t, BEGIN, t.activity+" begin", t.data)

	return t

}

// Task creates a new sub-task.  Parameter activity should be a short
// natural language description of the work that the Task represents,
// without any terminating punctuation.  Any data given here will be
// associated with the Task and reported with all its events.
func (x *Task) Task(activity string, data ...interface{}) *Task {
	return newtask(x, "", activity, data)
}

// Component creates a new Task object representing related long-lived
// functionality, rather than a directed, tightly scoped line of
// computation.  Parameter component should be a short lowercase
// string identifying the class, module, or other component that this
// Task represents.  The activity text of this Task is set to be
// "Component " + component.  Any data given will be associated with
// the Task and reported with all its events.
func (x *Task) Component(component string, data ...interface{}) *Task {
	return newtask(x, component, "Component " + component, data)
}

// AddData incorporates the given data into that associated and
// reported with this Task.  The rules for this construction are
// explained in CopyFrom.  This call does not generate a log event.
// The host Task is passed through as the return.  Among other things,
// this function is useful to silently accumulate data into the Task
// as it proceeds, to be reported when it concludes.
func (x *Task) AddData(data ...interface{}) *Task {
	x.data.CopyFrom(data)
	return x
}

// Event generates a user-specified log event.  Parameter event tags
// the class of the event, generally a short lowercase whitespace-free
// identifier.  A human-oriented text message is given as the msg
// parameter.  This should generally be static, short, use sentence
// capitalization but no terminating punctuation, and not itself
// include any data, which is better left to the structured data.  The
// variadic data parameter is aggregated as a D and reported with the
// event, as is the data permanently associated with the Task.  The
// given data is not associated to the Task permanently.
func (x *Task) Event(event string, msg string, data ...interface{}) {
	x.root.event(x, event, msg, DAggregate(data).CopyFrom(x.data))
}

// Info generates an informational log event.  A human-oriented text
// message is given as the msg parameter.  This should generally be
// static, short, use sentence capitalization but no terminating
// punctuation, and not itself include any data, which is better left
// to the structured data.  The variadic data parameter is aggregated
// as a D and reported with the event, as is the data permanently
// associated with the Task.  The given data is not associated to the
// Task permanently.
func (x *Task) Info(msg string, data ...interface{}) {
	x.root.event(x, INFO, msg, DAggregate(data).CopyFrom(x.data))
}

// Warning generates a warning log event indicating that a fault was
// encountered but the task is proceeding acceptably.  This should
// generally be static, short, use sentence capitalization but no
// terminating punctuation, and not itself include any data, which is
// better left to the structured data.  The variadic data parameter is
// aggregated as a D and reported with the event, as is the data
// permanently associated with the Task.  The given data is not
// associated to the Task permanently.
func (x *Task) Warning(msg string, data ...interface{}) {
	x.root.event(x, WARNING, msg, DAggregate(data).CopyFrom(x.data))
}

// Ready generates a ready log event reporting that the activity or
// component the Task represents is initialized and prepared to begin.
// The variadic data parameter is aggregated as a D and reported with
// the event, as is the data permanently associated with the Task.
// The given data is not associated to the Task permanently.
func (x *Task) Ready(data ...interface{}) {
	x.root.event(x, READY, x.activity+" ready",
		DAggregate(data).CopyFrom(x.data))
}

// Stopped generates a stopped log event reporting that the activity
// or component the Task represents has paused or shutdown.  The
// variadic data parameter is aggregated as a D and reported with the
// event, as is the data permanently associated with the Task.  The
// given data is not associated to the Task permanently.
func (x *Task) Stopped(data ...interface{}) {
	x.root.event(x, STOPPED, x.activity+" stopped",
		DAggregate(data).CopyFrom(x.data))
}

// Finalized generates an end log event reporting that the component
// the Task represents has ceased.  It is generally intended to be
// used for components, while Success is used for discrete activities.
// Continuing to use the Task is discouraged.  The variadic data
// parameter is aggregated as a D and reported with the event, as is
// the data permanently associated with the Task.  The given data is
// not associated to the Task permanently.
func (x *Task) Finalized(data ...interface{}) {
	x.root.event(x, END, x.activity+" finalized", DAggregate(data).CopyFrom(x.data))
}

// Success generates a success log event reporting that the activity
// the Task represents has concluded successfully.  It always returns
// nil.  Continuing to use the Task is discouraged.  The variadic data
// parameter is aggregated as a D and reported with the event, as is
// the data permanently associated with the Task.  The given data is
// not associated to the Task permanently.
func (x *Task) Success(data ...interface{}) error {
	x.root.event(x, SUCCESS, x.activity+" success", DAggregate(data).CopyFrom(x.data))
	return nil
}

// Error generates an error log event reporting an unrecoverable fault
// in an activity or component.  An error is returned wrapping the
// original error with a message reporting that the Task's activity
// has failed.  Continuing to use the Task is discouraged.  The
// variadic data parameter is aggregated as a D and embedded in the
// generated error.  It and the data permanently associated with the
// Task is reported with the event.  The reported source code position
// of the generated task error is adjusted to be the event invocation.
func (x *Task) Error(err error, data ...interface{}) error {
	m := x.activity + " failed"
	x.root.event(x, ERROR, m, D{"Error": err}.CopyFrom(DAggregate(data)).CopyFrom(x.data))

	e := wraperror(m, err, data)
	e.Locate(1)
	return e
}

// Failure generates an error log event reporting an unrecoverable
// fault.  Failure and Error are essentially the same, the difference
// being that Failure is the first point of fault while Error takes an
// underlying error typically returned from another function or
// component.  An error is returned reporting that the activity or
// component represented by the Task has failed due to the underlying
// cause given in the message.  Continuing to use the Task is
// discouraged.  The variadic data parameter is aggregated as a D and
// embedded in the generated task error.  It and the data permanently
// associated with the Task is reported with the event.  The reported
// source code position of the generated task error is adjusted to be
// the event invocation.
func (x *Task) Failure(msg string, data ...interface{}) error {
	err := newerror(msg, nil)
	err.Locate(1)

	m := x.activity + " failed"
	x.root.event(x, ERROR, m, D{"Error": err}.CopyFrom(DAggregate(data)).CopyFrom(x.data))

	e := wraperror(m, err, data)
	e.Locate(1)
	return e
}
<commit_msg>Fix extraneous blank fields in errors.<commit_after>package logberry

import (
	"sync/atomic"
)

// Task represents a particular component, function, or activity.  In
// general a Task is meant to be used within a single thread of
// execution, and the calling code is responsible for managing any
// concurrent manipulation.
type Task struct {
	uid uint64

	root *Root

	parent *Task

	component string

	activity string

	data D
}

var numtasks uint64

func newtaskuid() uint64 {
	// We have seen this atomic call cause problems on ARM...
	return atomic.AddUint64(&numtasks, 1) - 1
}

func newtask(parent *Task, component string, activity string, data []interface{}) *Task {

	t := &Task{
		uid:    newtaskuid(),
		parent: parent,
		activity: activity,
		data: DAggregate(data),
	}

	if parent != nil {
		t.root = parent.root
		t.component = parent.component
	} else {
		t.root = Std
	}

	if component != "" {
		t.component = component
	}

	t.root.event(t, BEGIN, t.activity+" begin", t.data)

	return t

}

// Task creates a new sub-task.  Parameter activity should be a short
// natural language description of the work that the Task represents,
// without any terminating punctuation.  Any data given here will be
// associated with the Task and reported with all its events.
func (x *Task) Task(activity string, data ...interface{}) *Task {
	return newtask(x, "", activity, data)
}

// Component creates a new Task object representing related long-lived
// functionality, rather than a directed, tightly scoped line of
// computation.  Parameter component should be a short lowercase
// string identifying the class, module, or other component that this
// Task represents.  The activity text of this Task is set to be
// "Component " + component.  Any data given will be associated with
// the Task and reported with all its events.
func (x *Task) Component(component string, data ...interface{}) *Task {
	return newtask(x, component, "Component " + component, data)
}

// AddData incorporates the given data into that associated and
// reported with this Task.  The rules for this construction are
// explained in CopyFrom.  This call does not generate a log event.
// The host Task is passed through as the return.  Among other things,
// this function is useful to silently accumulate data into the Task
// as it proceeds, to be reported when it concludes.
func (x *Task) AddData(data ...interface{}) *Task {
	x.data.CopyFrom(data)
	return x
}

// Event generates a user-specified log event.  Parameter event tags
// the class of the event, generally a short lowercase whitespace-free
// identifier.  A human-oriented text message is given as the msg
// parameter.  This should generally be static, short, use sentence
// capitalization but no terminating punctuation, and not itself
// include any data, which is better left to the structured data.  The
// variadic data parameter is aggregated as a D and reported with the
// event, as is the data permanently associated with the Task.  The
// given data is not associated to the Task permanently.
func (x *Task) Event(event string, msg string, data ...interface{}) {
	x.root.event(x, event, msg, DAggregate(data).CopyFrom(x.data))
}

// Info generates an informational log event.  A human-oriented text
// message is given as the msg parameter.  This should generally be
// static, short, use sentence capitalization but no terminating
// punctuation, and not itself include any data, which is better left
// to the structured data.  The variadic data parameter is aggregated
// as a D and reported with the event, as is the data permanently
// associated with the Task.  The given data is not associated to the
// Task permanently.
func (x *Task) Info(msg string, data ...interface{}) {
	x.root.event(x, INFO, msg, DAggregate(data).CopyFrom(x.data))
}

// Warning generates a warning log event indicating that a fault was
// encountered but the task is proceeding acceptably.  This should
// generally be static, short, use sentence capitalization but no
// terminating punctuation, and not itself include any data, which is
// better left to the structured data.  The variadic data parameter is
// aggregated as a D and reported with the event, as is the data
// permanently associated with the Task.  The given data is not
// associated to the Task permanently.
func (x *Task) Warning(msg string, data ...interface{}) {
	x.root.event(x, WARNING, msg, DAggregate(data).CopyFrom(x.data))
}

// Ready generates a ready log event reporting that the activity or
// component the Task represents is initialized and prepared to begin.
// The variadic data parameter is aggregated as a D and reported with
// the event, as is the data permanently associated with the Task.
// The given data is not associated to the Task permanently.
func (x *Task) Ready(data ...interface{}) {
	x.root.event(x, READY, x.activity+" ready",
		DAggregate(data).CopyFrom(x.data))
}

// Stopped generates a stopped log event reporting that the activity
// or component the Task represents has paused or shutdown.  The
// variadic data parameter is aggregated as a D and reported with the
// event, as is the data permanently associated with the Task.  The
// given data is not associated to the Task permanently.
func (x *Task) Stopped(data ...interface{}) {
	x.root.event(x, STOPPED, x.activity+" stopped",
		DAggregate(data).CopyFrom(x.data))
}

// Finalized generates an end log event reporting that the component
// the Task represents has ceased.  It is generally intended to be
// used for components, while Success is used for discrete activities.
// Continuing to use the Task is discouraged.  The variadic data
// parameter is aggregated as a D and reported with the event, as is
// the data permanently associated with the Task.  The given data is
// not associated to the Task permanently.
func (x *Task) Finalized(data ...interface{}) {
	x.root.event(x, END, x.activity+" finalized", DAggregate(data).CopyFrom(x.data))
}

// Success generates a success log event reporting that the activity
// the Task represents has concluded successfully.  It always returns
// nil.  Continuing to use the Task is discouraged.  The variadic data
// parameter is aggregated as a D and reported with the event, as is
// the data permanently associated with the Task.  The given data is
// not associated to the Task permanently.
func (x *Task) Success(data ...interface{}) error {
	x.root.event(x, SUCCESS, x.activity+" success", DAggregate(data).CopyFrom(x.data))
	return nil
}

// Error generates an error log event reporting an unrecoverable fault
// in an activity or component.  An error is returned wrapping the
// original error with a message reporting that the Task's activity
// has failed.  Continuing to use the Task is discouraged.  The
// variadic data parameter is aggregated as a D and embedded in the
// generated error.  It and the data permanently associated with the
// Task is reported with the event.  The reported source code position
// of the generated task error is adjusted to be the event invocation.
func (x *Task) Error(err error, data ...interface{}) error {
	m := x.activity + " failed"
	x.root.event(x, ERROR, m, D{"Error": DAggregate([]interface{}{err})}.CopyFrom(DAggregate(data)).CopyFrom(x.data))

	e := wraperror(m, err, data)
	e.Locate(1)
	return e
}

// Failure generates an error log event reporting an unrecoverable
// fault.  Failure and Error are essentially the same, the difference
// being that Failure is the first point of fault while Error takes an
// underlying error typically returned from another function or
// component.  An error is returned reporting that the activity or
// component represented by the Task has failed due to the underlying
// cause given in the message.  Continuing to use the Task is
// discouraged.  The variadic data parameter is aggregated as a D and
// embedded in the generated task error.  It and the data permanently
// associated with the Task is reported with the event.  The reported
// source code position of the generated task error is adjusted to be
// the event invocation.
func (x *Task) Failure(msg string, data ...interface{}) error {
	err := newerror(msg, nil)
	err.Locate(1)

	m := x.activity + " failed"
	x.root.event(x, ERROR, m, D{"Error": DAggregate([]interface{}{err})}.CopyFrom(DAggregate(data)).CopyFrom(x.data))

	e := wraperror(m, err, data)
	e.Locate(1)
	return e
}
<|endoftext|>


<commit_before>package CloudForest

import (
	"bufio"
	"encoding/csv"
	"io"
	"log"
	"strings"
)

func ParseARFF(input io.Reader) *FeatureMatrix {

	reader := bufio.NewReader(input)

	data := make([]Feature, 0, 100)
	lookup := make(map[string]int, 0)
	labels := make([]string, 0, 0)

	i := 0
	for {

		line, err := reader.ReadString('\n')
		if err != nil {
			log.Print("Error:", err)
			return nil
		}
		norm := strings.ToLower(line)

		if strings.HasPrefix(norm, "@data") {
			break
		}

		if strings.HasPrefix(norm, "@attribute") {
			vals := strings.Fields(line)

			if strings.ToLower(vals[2]) == "numeric" {
				data = append(data, &DenseNumFeature{
					make([]float64, 0, 0),
					make([]bool, 0, 0),
					vals[1]})
			} else {
				data = append(data, &DenseCatFeature{
					&CatMap{make(map[string]int, 0),
						make([]string, 0, 0)},
					make([]int, 0, 0),
					make([]bool, 0, 0),
					vals[1],
					false})
			}

			lookup[vals[1]] = i
			labels = append(labels, vals[1])
			i++
		}

	}

	fm := &FeatureMatrix{data, lookup, labels}

	csvdata := csv.NewReader(reader)
	//csvdata.Comma = ','

	fm.LoadCases(csvdata, false)
	return fm

}
<commit_msg> fix to arff parsing<commit_after>package CloudForest

import (
	"bufio"
	"encoding/csv"
	"io"
	"log"
	"strings"
)

func ParseARFF(input io.Reader) *FeatureMatrix {

	reader := bufio.NewReader(input)

	data := make([]Feature, 0, 100)
	lookup := make(map[string]int, 0)
	labels := make([]string, 0, 0)

	i := 0
	for {

		line, err := reader.ReadString('\n')
		if err != nil {
			log.Print("Error:", err)
			return nil
		}
		norm := strings.ToLower(line)

		if strings.HasPrefix(norm, "@data") {
			break
		}

		if strings.HasPrefix(norm, "@attribute") {
			vals := strings.Fields(line)

			if strings.ToLower(vals[2]) == "numeric" || strings.ToLower(vals[2]) == "real" {
				data = append(data, &DenseNumFeature{
					make([]float64, 0, 0),
					make([]bool, 0, 0),
					vals[1]})
			} else {
				data = append(data, &DenseCatFeature{
					&CatMap{make(map[string]int, 0),
						make([]string, 0, 0)},
					make([]int, 0, 0),
					make([]bool, 0, 0),
					vals[1],
					false})
			}

			lookup[vals[1]] = i
			labels = append(labels, vals[1])
			i++
		}

	}

	fm := &FeatureMatrix{data, lookup, labels}

	csvdata := csv.NewReader(reader)
	//csvdata.Comma = ','

	fm.LoadCases(csvdata, false)
	return fm

}
<|endoftext|>