<commit_before>/**
 * (C) Copyright 2013, Deft Labs
 *
 * 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 dlshared

import (
	"time"
	"syscall"
)

const (
	nanosecondsPerMillisecond float64 = 1000000.0
)

// Returns the time from the milliseconds since epoch. This returns the time in UTC.
func TimeFromMillis(timeInMillis int64) *time.Time {
	theTime := time.Unix(timeInMillis/1000, 0)
	location, _ := time.LoadLocation("UTC")
	theTime = theTime.In(location)
	return &theTime
}

// Convert a time struct to milliseconds since epoch.
func TimeToMillis(tv *time.Time) int64 { return tv.UnixNano() / 1e6 }

func NowInUtc() *time.Time {
	location, _ := time.LoadLocation("UTC")
	time := time.Now().In(location)
	return &time
}

func NowInUtcMinusSeconds(seconds int) *time.Time {
	now := NowInUtc()
	adjusted := now.Add((time.Duration(seconds)*time.Second)*-1)
	return &adjusted
}

// Convert a duration to milliseconds.
func DurationToMillis(dur *time.Duration) int64 { return int64(float64(dur.Nanoseconds()) / nanosecondsPerMillisecond) }

// Get the current time in millis since epoch. Source from stackoverflow:
// http://stackoverflow.com/questions/6161839/go-time-milliseconds
func CurrentTimeInMillis() int64 {
	tv := new(syscall.Timeval)
	syscall.Gettimeofday(tv)
	return (int64(tv.Sec)*1e3 + int64(tv.Usec)/1e3)
}

// Returns the current time in seconds since epoch (i.e., a unix timestamp). Source from stackoverflow:
// http://stackoverflow.com/questions/9539108/obtaining-a-unix-timestamp-in-go-language-current-time-in-seconds-since-epoch
func CurrentTimeInSeconds() int32 { return int32(time.Now().Unix()) }

// NowTimeUnixStr returns the date in unix date string format e.g., Wed Dec 11 19:03:18 EST 2013
func NowTimeUnixStr() string { return time.Now().Format(time.UnixDate) }

<commit_msg>added start of today/tomorrow functions.<commit_after>/**
 * (C) Copyright 2013, Deft Labs
 *
 * 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 dlshared

import (
	"time"
	"syscall"
)

const (
	nanosecondsPerMillisecond float64 = 1000000.0
)

// Returns the time configured to the start of the current day (00:00:00 etc). The current
// day is defined using UTC.
func TimeStartOfCurrentDay() *time.Time {
	location, _ := time.LoadLocation("UTC")
	now := NowInUtc()
	startOfCurrentDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, location)
	return &startOfCurrentDay
}

// Returns the time configured to the start of the next day (00:00:00 etc). The current
// day is defined using UTC.
func TimeStartOfNextDay() *time.Time {
	location, _ := time.LoadLocation("UTC")
	tomorrow := NowInUtc().Add(time.Duration(24) * time.Hour)
	startOfNextDay := time.Date(tomorrow.Year(), tomorrow.Month(), tomorrow.Day(), 0, 0, 0, 0, location)
	return &startOfNextDay
}

// Returns the time from the milliseconds since epoch. This returns the time in UTC.
func TimeFromMillis(timeInMillis int64) *time.Time {
	theTime := time.Unix(timeInMillis/1000, 0)
	location, _ := time.LoadLocation("UTC")
	theTime = theTime.In(location)
	return &theTime
}

// Convert a time struct to milliseconds since epoch.
func TimeToMillis(tv *time.Time) int64 { return tv.UnixNano() / 1e6 }

func NowInUtc() *time.Time {
	location, _ := time.LoadLocation("UTC")
	time := time.Now().In(location)
	return &time
}

func NowInUtcMinusSeconds(seconds int) *time.Time {
	now := NowInUtc()
	adjusted := now.Add((time.Duration(seconds)*time.Second)*-1)
	return &adjusted
}

// Convert a duration to milliseconds.
func DurationToMillis(dur *time.Duration) int64 { return int64(float64(dur.Nanoseconds()) / nanosecondsPerMillisecond) }

// Get the current time in millis since epoch. Source from stackoverflow:
// http://stackoverflow.com/questions/6161839/go-time-milliseconds
func CurrentTimeInMillis() int64 {
	tv := new(syscall.Timeval)
	syscall.Gettimeofday(tv)
	return (int64(tv.Sec)*1e3 + int64(tv.Usec)/1e3)
}

// Returns the current time in seconds since epoch (i.e., a unix timestamp). Source from stackoverflow:
// http://stackoverflow.com/questions/9539108/obtaining-a-unix-timestamp-in-go-language-current-time-in-seconds-since-epoch
func CurrentTimeInSeconds() int32 { return int32(time.Now().Unix()) }

// NowTimeUnixStr returns the date in unix date string format e.g., Wed Dec 11 19:03:18 EST 2013
func NowTimeUnixStr() string { return time.Now().Format(time.UnixDate) }

<|endoftext|>


<commit_before>package kcp

import (
	"container/heap"
	"runtime"
	"sync"
	"time"
)

// SystemTimedSched is the library level timed-scheduler
var SystemTimedSched *TimedSched = NewTimedSched(runtime.NumCPU())

type timedFunc struct {
	execute func()
	ts      time.Time
}

// a heap for sorted timed function
type timedFuncHeap []timedFunc

func (h timedFuncHeap) Len() int            { return len(h) }
func (h timedFuncHeap) Less(i, j int) bool  { return h[i].ts.Before(h[j].ts) }
func (h timedFuncHeap) Swap(i, j int)       { h[i], h[j] = h[j], h[i] }
func (h *timedFuncHeap) Push(x interface{}) { *h = append(*h, x.(timedFunc)) }
func (h *timedFuncHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

// TimedSched represents the control struct for timed parallel scheduler
type TimedSched struct {
	// prepending tasks
	prependTasks    []timedFunc
	prependLock     sync.Mutex
	chPrependNotify chan struct{}

	// tasks will be distributed through chTask
	chTask chan timedFunc

	dieOnce sync.Once
	die     chan struct{}
}

// NewTimedSched creates a parallel-scheduler with given parallelization
func NewTimedSched(parallel int) *TimedSched {
	ts := new(TimedSched)
	ts.chTask = make(chan timedFunc)
	ts.die = make(chan struct{})
	ts.chPrependNotify = make(chan struct{}, 1)

	for i := 0; i < parallel; i++ {
		go ts.sched()
	}
	go ts.prepend()
	return ts
}

func (ts *TimedSched) sched() {
	var tasks timedFuncHeap
	timer := time.NewTimer(0)
	for {
		select {
		case task := <-ts.chTask:
			now := time.Now()
			if now.After(task.ts) {
				// already delayed! execute immediately
				task.execute()
			} else {
				heap.Push(&tasks, task)
				// activate timer if timer has hibernated due to 0 tasks.
				if tasks.Len() == 1 {
					timer.Reset(task.ts.Sub(now))
				}
			}
		case <-timer.C:
			for tasks.Len() > 0 {
				now := time.Now()
				if now.After(tasks[0].ts) {
					heap.Pop(&tasks).(timedFunc).execute()
				} else {
					timer.Reset(tasks[0].ts.Sub(now))
					break
				}
			}
		case <-ts.die:
			return
		}
	}
}

func (ts *TimedSched) prepend() {
	var tasks []timedFunc
	for {
		select {
		case <-ts.chPrependNotify:
			ts.prependLock.Lock()
			// keep cap to reuse slice
			if cap(tasks) < cap(ts.prependTasks) {
				tasks = make([]timedFunc, 0, cap(ts.prependTasks))
			}
			tasks = tasks[:len(ts.prependTasks)]
			copy(tasks, ts.prependTasks)
			ts.prependTasks = ts.prependTasks[:0]
			ts.prependLock.Unlock()

			for k := range tasks {
				select {
				case ts.chTask <- tasks[k]:
				case <-ts.die:
					return
				}
			}
			tasks = tasks[:0]
		case <-ts.die:
			return
		}
	}
}

// Put a function awaiting to be executed
func (ts *TimedSched) Put(f func(), duration time.Duration) {
	ts.prependLock.Lock()
	ts.prependTasks = append(ts.prependTasks, timedFunc{f, time.Now().Add(duration)})
	ts.prependLock.Unlock()

	select {
	case ts.chPrependNotify <- struct{}{}:
	default:
	}
}

// Close terminates this scheduler
func (ts *TimedSched) Close() { ts.dieOnce.Do(func() { close(ts.die) }) }
<commit_msg>prevent slice from holding reference to closure<commit_after>package kcp

import (
	"container/heap"
	"runtime"
	"sync"
	"time"
)

// SystemTimedSched is the library level timed-scheduler
var SystemTimedSched *TimedSched = NewTimedSched(runtime.NumCPU())

type timedFunc struct {
	execute func()
	ts      time.Time
}

// a heap for sorted timed function
type timedFuncHeap []timedFunc

func (h timedFuncHeap) Len() int            { return len(h) }
func (h timedFuncHeap) Less(i, j int) bool  { return h[i].ts.Before(h[j].ts) }
func (h timedFuncHeap) Swap(i, j int)       { h[i], h[j] = h[j], h[i] }
func (h *timedFuncHeap) Push(x interface{}) { *h = append(*h, x.(timedFunc)) }
func (h *timedFuncHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	old[n-1].execute = nil // avoid memory leak
	*h = old[0 : n-1]
	return x
}

// TimedSched represents the control struct for timed parallel scheduler
type TimedSched struct {
	// prepending tasks
	prependTasks    []timedFunc
	prependLock     sync.Mutex
	chPrependNotify chan struct{}

	// tasks will be distributed through chTask
	chTask chan timedFunc

	dieOnce sync.Once
	die     chan struct{}
}

// NewTimedSched creates a parallel-scheduler with given parallelization
func NewTimedSched(parallel int) *TimedSched {
	ts := new(TimedSched)
	ts.chTask = make(chan timedFunc)
	ts.die = make(chan struct{})
	ts.chPrependNotify = make(chan struct{}, 1)

	for i := 0; i < parallel; i++ {
		go ts.sched()
	}
	go ts.prepend()
	return ts
}

func (ts *TimedSched) sched() {
	var tasks timedFuncHeap
	timer := time.NewTimer(0)
	for {
		select {
		case task := <-ts.chTask:
			now := time.Now()
			if now.After(task.ts) {
				// already delayed! execute immediately
				task.execute()
			} else {
				heap.Push(&tasks, task)
				// activate timer if timer has hibernated due to 0 tasks.
				if tasks.Len() == 1 {
					timer.Reset(task.ts.Sub(now))
				}
			}
		case <-timer.C:
			for tasks.Len() > 0 {
				now := time.Now()
				if now.After(tasks[0].ts) {
					heap.Pop(&tasks).(timedFunc).execute()
				} else {
					timer.Reset(tasks[0].ts.Sub(now))
					break
				}
			}
		case <-ts.die:
			return
		}
	}
}

func (ts *TimedSched) prepend() {
	var tasks []timedFunc
	for {
		select {
		case <-ts.chPrependNotify:
			ts.prependLock.Lock()
			// keep cap to reuse slice
			if cap(tasks) < cap(ts.prependTasks) {
				tasks = make([]timedFunc, 0, cap(ts.prependTasks))
			}
			tasks = tasks[:len(ts.prependTasks)]
			copy(tasks, ts.prependTasks)
			for k := range ts.prependTasks {
				ts.prependTasks[k].execute = nil // avoid memory leak
			}
			ts.prependTasks = ts.prependTasks[:0]
			ts.prependLock.Unlock()

			for k := range tasks {
				select {
				case ts.chTask <- tasks[k]:
					tasks[k].execute = nil // avoid memory leak
				case <-ts.die:
					return
				}
			}
			tasks = tasks[:0]
		case <-ts.die:
			return
		}
	}
}

// Put a function awaiting to be executed
func (ts *TimedSched) Put(f func(), duration time.Duration) {
	ts.prependLock.Lock()
	ts.prependTasks = append(ts.prependTasks, timedFunc{f, time.Now().Add(duration)})
	ts.prependLock.Unlock()

	select {
	case ts.chPrependNotify <- struct{}{}:
	default:
	}
}

// Close terminates this scheduler
func (ts *TimedSched) Close() { ts.dieOnce.Do(func() { close(ts.die) }) }
<|endoftext|>


<commit_before>// Copyright 2017 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-vgo/gt/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

package gt

import (
	"log"
)

const (
	version string = "v0.10.0.78, Mount Kailash!"
)

// GetVersion get version
func GetVersion() string {
	return version
}

// Try handler error
func Try(fun func(), handler func(interface{})) {
	defer func() {
		if err := recover(); err != nil {
			handler(err)
		}
	}()
	fun()
}

// CheckErr check error
func CheckErr(err error) {
	if err != nil {
		panic(err)
	}
}

// LogErr println error
func LogErr(err error) {
	if err != nil {
		log.Println("error: ", err)
	}
}
<commit_msg>add sleep function support<commit_after>// Copyright 2017 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-vgo/gt/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

package gt

import (
	"log"
	"time"
)

const (
	version string = "v0.10.0.78, Mount Kailash!"
)

// GetVersion get version
func GetVersion() string {
	return version
}

// Try handler error
func Try(fun func(), handler func(interface{})) {
	defer func() {
		if err := recover(); err != nil {
			handler(err)
		}
	}()
	fun()
}

// MilliSleep sleep tm milli second
func MilliSleep(tm int) {
	time.Sleep(time.Duration(tm) * time.Millisecond)
}

// Sleep time.Sleep tm second
func Sleep(tm int) {
	time.Sleep(time.Duration(tm) * time.Second)
}

// CheckErr check error
func CheckErr(err error) {
	if err != nil {
		panic(err)
	}
}

// LogErr println error
func LogErr(err error) {
	if err != nil {
		log.Println("error: ", err)
	}
}
<|endoftext|>


<commit_before>package ha

import (
	"fmt"
	"time"

	"golang.org/x/net/context"
)

func recoverWrapper(fn func()) (err error) {
	defer func() {
		switch e := recover().(type) {
		case nil:
		case error:
			err = e
		case interface{}:
			err = fmt.Errorf("%s", err)
		}
	}()

	fn()
	return
}

type config struct {
	maxRestart   uint
	noLimit      bool
	restartDelay time.Duration
	onStop       func(error)
	cancelCtx    context.Context
}

// CancelCtx when ctx cancled, fn will not restart again
func CancelCtx(ctx context.Context) func(conf *config) {
	return func(conf *config) {
		conf.cancelCtx = ctx
	}
}

// OnStop run onStop when fn stopped
func OnStop(onStop func(error)) func(conf *config) {
	return func(conf *config) {
		conf.onStop = onStop
	}
}

// MaxRestart max restart times
func MaxRestart(max uint) func(conf *config) {
	return func(conf *config) {
		conf.noLimit = false
		conf.maxRestart = max
	}
}

// RestartDelay wait for d time before restart fn
func RestartDelay(d time.Duration) func(conf *config) {
	return func(conf *config) {
		conf.restartDelay = d
	}
}

// Watch run then watch fn, if fn returned, run it again
func Watch(fn func(), setups ...func(*config)) {
	conf := &config{
		noLimit:   true,
		onStop:    func(error) {},
		cancelCtx: context.Background(),
	}
	for _, setup := range setups {
		setup(conf)
	}
	for {
		conf.onStop(recoverWrapper(fn))
		select {
		case <-conf.cancelCtx.Done():
			return
		default:
		}
		time.Sleep(conf.restartDelay)
		if conf.noLimit {
			continue
		}
		if conf.maxRestart--; conf.maxRestart <= 0 {
			return
		}
	}
}
<commit_msg>fix typo in recoverWrapper<commit_after>package ha

import (
	"fmt"
	"time"

	"golang.org/x/net/context"
)

func recoverWrapper(fn func()) (err error) {
	defer func() {
		switch e := recover().(type) {
		case nil:
		case error:
			err = e
		case interface{}:
			err = fmt.Errorf("%s", e)
		}
	}()

	fn()
	return
}

type config struct {
	maxRestart   uint
	noLimit      bool
	restartDelay time.Duration
	onStop       func(error)
	cancelCtx    context.Context
}

// CancelCtx when ctx cancled, fn will not restart again
func CancelCtx(ctx context.Context) func(conf *config) {
	return func(conf *config) {
		conf.cancelCtx = ctx
	}
}

// OnStop run onStop when fn stopped
func OnStop(onStop func(error)) func(conf *config) {
	return func(conf *config) {
		conf.onStop = onStop
	}
}

// MaxRestart max restart times
func MaxRestart(max uint) func(conf *config) {
	return func(conf *config) {
		conf.noLimit = false
		conf.maxRestart = max
	}
}

// RestartDelay wait for d time before restart fn
func RestartDelay(d time.Duration) func(conf *config) {
	return func(conf *config) {
		conf.restartDelay = d
	}
}

// Watch run then watch fn, if fn returned, run it again
func Watch(fn func(), setups ...func(*config)) {
	conf := &config{
		noLimit:   true,
		onStop:    func(error) {},
		cancelCtx: context.Background(),
	}
	for _, setup := range setups {
		setup(conf)
	}
	for {
		conf.onStop(recoverWrapper(fn))
		select {
		case <-conf.cancelCtx.Done():
			return
		default:
		}
		time.Sleep(conf.restartDelay)
		if conf.noLimit {
			continue
		}
		if conf.maxRestart--; conf.maxRestart <= 0 {
			return
		}
	}
}
<|endoftext|>


<commit_before>package pcap

import (
	"encoding/binary"
	"fmt"
	"io"
)

// FileHeader is the parsed header of a pcap file.
// http://wiki.wireshark.org/Development/LibpcapFileFormat
type FileHeader struct {
	MagicNumber  uint32
	VersionMajor uint16
	VersionMinor uint16
	TimeZone     int32
	SigFigs      uint32
	SnapLen      uint32
	Network      uint32
}

type PacketTime struct {
	Sec  int32
	Usec int32
}

// Packet is a single packet parsed from a pcap file.
type Packet struct {
	Time   PacketTime // packet send/receive time
	Caplen uint32     // bytes stored in the file (caplen <= len)
	Len    uint32     // bytes sent/received
	Data   []byte     // packet data

	Type    int // protocol type, see LINKTYPE_*
	DestMac uint64
	SrcMac  uint64

	Headers []interface{} // decoded headers, in order
	Payload []byte        // remaining non-header bytes
}

// Reader parses pcap files.
type Reader struct {
	flip         bool
	buf          io.Reader
	err          error
	fourBytes    []byte
	twoBytes     []byte
	sixteenBytes []byte
	Header       FileHeader
}

// NewReader reads pcap data from an io.Reader.
func NewReader(reader io.Reader) (*Reader, error) {
	r := &Reader{
		buf:          reader,
		fourBytes:    make([]byte, 4),
		twoBytes:     make([]byte, 2),
		sixteenBytes: make([]byte, 16),
	}
	magic := r.readUint32()
	if magic == 0xa1b2c3d4 {
		r.flip = false
	} else if magic == 0xd4c3b2a1 {
		r.flip = true
	} else {
		return nil, fmt.Errorf("pcap: bad magic number: %0x", magic)
	}
	r.Header = FileHeader{
		MagicNumber:  0xa1b2c3d4,
		VersionMajor: r.readUint16(),
		VersionMinor: r.readUint16(),
		TimeZone:     r.readInt32(),
		SigFigs:      r.readUint32(),
		SnapLen:      r.readUint32(),
		Network:      r.readUint32(),
	}
	return r, nil
}

// Next returns the next packet or nil if no more packets can be read.
func (r *Reader) Next() *Packet {
	d := r.sixteenBytes
	r.err = r.read(d)
	if r.err != nil {
		return nil
	}
	timeSec := asUint32(d[0:4], r.flip)
	timeUsec := asUint32(d[4:8], r.flip)
	capLen := asUint32(d[8:12], r.flip)
	origLen := asUint32(d[12:16], r.flip)

	data := make([]byte, capLen)
	if r.err = r.read(data); r.err != nil {
		return nil
	}
	return &Packet{
		Time: PacketTime{
			Sec:  int32(timeSec),
			Usec: int32(timeUsec),
		},
		Caplen: capLen,
		Len:    origLen,
		Data:   data,
	}
}

func (r *Reader) read(data []byte) error {
	var err error
	n, err := r.buf.Read(data)
	for err == nil && n != len(data) {
		var chunk int
		chunk, err = r.buf.Read(data[n:])
		n += chunk
	}
	if len(data) == n {
		return nil
	}
	return err
}

func (r *Reader) readUint32() uint32 {
	data := r.fourBytes
	if r.err = r.read(data); r.err != nil {
		return 0
	}
	return asUint32(data, r.flip)
}

func (r *Reader) readInt32() int32 {
	data := r.fourBytes
	if r.err = r.read(data); r.err != nil {
		return 0
	}
	return int32(asUint32(data, r.flip))
}

func (r *Reader) readUint16() uint16 {
	data := r.twoBytes
	if r.err = r.read(data); r.err != nil {
		return 0
	}
	return asUint16(data, r.flip)
}

// Writer writes a pcap file.
type Writer struct {
	writer io.Writer
	buf    []byte
}

// NewWriter creates a Writer that stores output in an io.Writer.
// The FileHeader is written immediately.
func NewWriter(writer io.Writer, header *FileHeader) (*Writer, error) {
	w := &Writer{
		writer: writer,
		buf:    make([]byte, 24),
	}
	e := encoder{w.buf}
	e.put4(header.MagicNumber)
	e.put2(header.VersionMajor)
	e.put2(header.VersionMinor)
	e.put4(uint32(header.TimeZone))
	e.put4(header.SigFigs)
	e.put4(header.SnapLen)
	e.put4(header.Network)
	_, err := writer.Write(w.buf)
	if err != nil {
		return nil, err
	}
	return w, nil
}

// Writer writes a packet to the underlying writer.
func (w *Writer) Write(pkt *Packet) error {
	e := encoder{w.buf}
	e.put4(uint32(pkt.Time.Sec))
	e.put4(uint32(pkt.Time.Usec))
	e.put4(pkt.Caplen)
	e.put4(pkt.Len)
	_, err := w.writer.Write(w.buf[:16])
	if err != nil {
		return err
	}
	_, err = w.writer.Write(pkt.Data)
	return err
}

type encoder struct {
	buf []byte
}

func (e *encoder) put4(v uint32) {
	e.buf[0] = byte(v)
	e.buf[1] = byte(v >> 8)
	e.buf[2] = byte(v >> 16)
	e.buf[3] = byte(v >> 24)
	e.buf = e.buf[4:]
}

func (e *encoder) put2(v uint16) {
	e.buf[0] = byte(v)
	e.buf[1] = byte(v >> 8)
	e.buf = e.buf[2:]
}

func asUint32(data []byte, flip bool) uint32 {
	if flip {
		return binary.BigEndian.Uint32(data)
	}
	return binary.LittleEndian.Uint32(data)
}

func asUint16(data []byte, flip bool) uint16 {
	if flip {
		return binary.BigEndian.Uint16(data)
	}
	return binary.LittleEndian.Uint16(data)
}
<commit_msg>use more encoding/binary<commit_after>package pcap

import (
	"encoding/binary"
	"fmt"
	"io"
)

// FileHeader is the parsed header of a pcap file.
// http://wiki.wireshark.org/Development/LibpcapFileFormat
type FileHeader struct {
	MagicNumber  uint32
	VersionMajor uint16
	VersionMinor uint16
	TimeZone     int32
	SigFigs      uint32
	SnapLen      uint32
	Network      uint32
}

type PacketTime struct {
	Sec  int32
	Usec int32
}

// Packet is a single packet parsed from a pcap file.
type Packet struct {
	Time   PacketTime // packet send/receive time
	Caplen uint32     // bytes stored in the file (caplen <= len)
	Len    uint32     // bytes sent/received
	Data   []byte     // packet data

	Type    int // protocol type, see LINKTYPE_*
	DestMac uint64
	SrcMac  uint64

	Headers []interface{} // decoded headers, in order
	Payload []byte        // remaining non-header bytes
}

// Reader parses pcap files.
type Reader struct {
	flip         bool
	buf          io.Reader
	err          error
	fourBytes    []byte
	twoBytes     []byte
	sixteenBytes []byte
	Header       FileHeader
}

// NewReader reads pcap data from an io.Reader.
func NewReader(reader io.Reader) (*Reader, error) {
	r := &Reader{
		buf:          reader,
		fourBytes:    make([]byte, 4),
		twoBytes:     make([]byte, 2),
		sixteenBytes: make([]byte, 16),
	}
	switch magic := r.readUint32(); magic {
	case 0xa1b2c3d4:
		r.flip = false
	case 0xd4c3b2a1:
		r.flip = true
	default:
		return nil, fmt.Errorf("pcap: bad magic number: %0x", magic)
	}
	r.Header = FileHeader{
		MagicNumber:  0xa1b2c3d4,
		VersionMajor: r.readUint16(),
		VersionMinor: r.readUint16(),
		TimeZone:     r.readInt32(),
		SigFigs:      r.readUint32(),
		SnapLen:      r.readUint32(),
		Network:      r.readUint32(),
	}
	return r, nil
}

// Next returns the next packet or nil if no more packets can be read.
func (r *Reader) Next() *Packet {
	d := r.sixteenBytes
	r.err = r.read(d)
	if r.err != nil {
		return nil
	}
	timeSec := asUint32(d[0:4], r.flip)
	timeUsec := asUint32(d[4:8], r.flip)
	capLen := asUint32(d[8:12], r.flip)
	origLen := asUint32(d[12:16], r.flip)

	data := make([]byte, capLen)
	if r.err = r.read(data); r.err != nil {
		return nil
	}
	return &Packet{
		Time: PacketTime{
			Sec:  int32(timeSec),
			Usec: int32(timeUsec),
		},
		Caplen: capLen,
		Len:    origLen,
		Data:   data,
	}
}

func (r *Reader) read(data []byte) error {
	var err error
	n, err := r.buf.Read(data)
	for err == nil && n != len(data) {
		var chunk int
		chunk, err = r.buf.Read(data[n:])
		n += chunk
	}
	if len(data) == n {
		return nil
	}
	return err
}

func (r *Reader) readUint32() uint32 {
	data := r.fourBytes
	if r.err = r.read(data); r.err != nil {
		return 0
	}
	return asUint32(data, r.flip)
}

func (r *Reader) readInt32() int32 {
	data := r.fourBytes
	if r.err = r.read(data); r.err != nil {
		return 0
	}
	return int32(asUint32(data, r.flip))
}

func (r *Reader) readUint16() uint16 {
	data := r.twoBytes
	if r.err = r.read(data); r.err != nil {
		return 0
	}
	return asUint16(data, r.flip)
}

// Writer writes a pcap file.
type Writer struct {
	writer io.Writer
	buf    []byte
}

// NewWriter creates a Writer that stores output in an io.Writer.
// The FileHeader is written immediately.
func NewWriter(writer io.Writer, header *FileHeader) (*Writer, error) {
	w := &Writer{
		writer: writer,
		buf:    make([]byte, 24),
	}
	binary.LittleEndian.PutUint32(w.buf, header.MagicNumber)
	binary.LittleEndian.PutUint16(w.buf[4:], header.VersionMajor)
	binary.LittleEndian.PutUint16(w.buf[6:], header.VersionMinor)
	binary.LittleEndian.PutUint32(w.buf[8:], uint32(header.TimeZone))
	binary.LittleEndian.PutUint32(w.buf[12:], header.SigFigs)
	binary.LittleEndian.PutUint32(w.buf[16:], header.SnapLen)
	binary.LittleEndian.PutUint32(w.buf[20:], header.Network)
	if _, err := writer.Write(w.buf); err != nil {
		return nil, err
	}
	return w, nil
}

// Writer writes a packet to the underlying writer.
func (w *Writer) Write(pkt *Packet) error {
	binary.LittleEndian.PutUint32(w.buf, uint32(pkt.Time.Sec))
	binary.LittleEndian.PutUint32(w.buf[4:], uint32(pkt.Time.Usec))
	binary.LittleEndian.PutUint32(w.buf[8:], uint32(pkt.Time.Sec))
	binary.LittleEndian.PutUint32(w.buf[12:], pkt.Len)
	if _, err := w.writer.Write(w.buf[:16]); err !=nil {
		return err
	}
	_, err := w.writer.Write(pkt.Data)
	return err
}

func asUint32(data []byte, flip bool) uint32 {
	if flip {
		return binary.BigEndian.Uint32(data)
	}
	return binary.LittleEndian.Uint32(data)
}

func asUint16(data []byte, flip bool) uint16 {
	if flip {
		return binary.BigEndian.Uint16(data)
	}
	return binary.LittleEndian.Uint16(data)
}
<|endoftext|>


<commit_before>package jo

// Parsing events.
type Event int

const (
	None = iota
	SyntaxError

	ObjectStart
	ObjectEnd
	KeyStart
	KeyEnd
	ArrayStart
	ArrayEnd

	StringStart
	StringEnd
	NumberStart
	NumberEnd
	BoolStart
	BoolEnd
	NullStart
	NullEnd
)

// Parser states.
const (
	_StateValue = iota
	_StateDone

	_StateObjectKeyOrEnd   // {
	_StateObjectColon      // {"foo"
	_StateObjectCommaOrEnd // {"foo":"bar"

	_StateArrayValueOrEnd // [
	_StateArrayCommaOrEnd // ["any value"
	_StateArrayValue      // ["any value",

	// leading whitespace should be consumed from all states
	// above this line
	_AllowWhitespace

	_StateStringUnicode  // "\u
	_StateStringUnicode2 // "\u1
	_StateStringUnicode3 // "\u12
	_StateStringUnicode4 // "\u123
	_StateString         // "
	_StateStringEscaped  // "\

	_StateKeyUnicode  // "\u
	_StateKeyUnicode2 // "\u1
	_StateKeyUnicode3 // "\u12
	_StateKeyUnicode4 // "\u123
	_StateKey         // "
	_StateKeyEscaped  // "\

	_StateNumberNegative      // -
	_StateNumberZero          // 0
	_StateNumber              // 123
	_StateNumberDotFirstDigit // 123.
	_StateNumberDotDigit      // 123.4
	_StateNumberExpSign       // 123e
	_StateNumberExpFirstDigit // 123e+
	_StateNumberExpDigit      // 123e+1

	_StateTrue  // t
	_StateTrue2 // tr
	_StateTrue3 // tru

	_StateFalse  // f
	_StateFalse2 // fa
	_StateFalse3 // fal
	_StateFalse4 // fals

	_StateNull  // n
	_StateNull2 // nu
	_StateNull3 // nul

	_StateSyntaxError
)

// Our own little implementation of the `error` interface.
type syntaxError string

func (e syntaxError) Error() string {
	return string(e)
}

// Parser state machine.
type Parser struct {
	state int
	queue []int
	err   error
}

// Parses a byte slice containing JSON data. Returns the number of bytes
// read and an appropriate Event.
func (p *Parser) Parse(input []byte) (int, Event) {
	for i := 0; i < len(input); i++ {
		b := input[i]

		// optionally trim leading whitespace
		if p.state < _AllowWhitespace &&
			(b == ' ' || b == '\t' || b == '\n' || b == '\r') {
			continue
		}

		switch p.state {
		case _StateValue:
			switch {
			case b == '{':
				p.state = _StateObjectKeyOrEnd
				return i + 1, ObjectStart
			case b == '[':
				p.state = _StateArrayValueOrEnd
				return i + 1, ArrayStart
			case b == '"':
				p.state = _StateString
				return i + 1, StringStart
			case b == '-':
				p.state = _StateNumberNegative
				return i + 1, NumberStart
			case b == '0':
				p.state = _StateNumberZero
				return i + 1, NumberStart
			case '1' <= b && b <= '9':
				p.state = _StateNumber
				return i + 1, NumberStart
			case b == 't':
				p.state = _StateTrue
				return i + 1, BoolStart
			case b == 'f':
				p.state = _StateFalse
				return i + 1, BoolStart
			case b == 'n':
				p.state = _StateNull
				return i + 1, NullStart
			default:
				return i, p.error(`_StateValue: @todo`)
			}

		case _StateObjectKeyOrEnd:
			if b == '}' {
				p.state = p.next()
				return i + 1, ObjectEnd
			}
			if b != '"' {
				return i, p.error(`_StateObjectKeyOrEnd: @todo`)
			}

			p.state = _StateKey
			return i + 1, KeyStart

		case _StateObjectColon:
			if b != ':' {
				return i, p.error(`_StateObjectKeyOrEnd: @todo`)
			}

			p.push(_StateObjectCommaOrEnd)
			p.state = _StateValue

		case _StateObjectCommaOrEnd:
			switch b {
			case '}':
				p.state = p.next()
				return i + 1, ObjectEnd
			case ',':
				p.push(_StateObjectCommaOrEnd)
				p.state = _StateValue
			default:
				return i, p.error(`_StateObjectCommaOrEnd: @todo`)
			}

		case _StateArrayValueOrEnd:
			if b == ']' {
				p.state = p.next()
				return i + 1, ArrayEnd
			}

			p.push(_StateArrayCommaOrEnd)
			p.state = _StateValue
			i-- // rewind and let _StateValue do the parsing

		case _StateArrayCommaOrEnd:
			switch b {
			case ']':
				p.state = p.next()
				return i + 1, ArrayEnd
			case ',':
				p.push(_StateArrayCommaOrEnd)
				p.state = _StateValue
			default:
				return i, p.error(`_StateArrayCommaOrEnd: @todo`)
			}

		case _StateStringUnicode, _StateKeyUnicode,
			_StateStringUnicode2, _StateKeyUnicode2,
			_StateStringUnicode3, _StateKeyUnicode3,
			_StateStringUnicode4, _StateKeyUnicode4:
			switch {
			case '0' <= b && b <= '9':
			case 'a' <= b && b <= 'f':
			case 'A' <= b && b <= 'F':
			default:
				return i, p.error(`_StateStringUnicodeX: @todo`)
			}

			// note that _State{String,Key}Unicode4 + 1 == _State{String/Key}
			p.state++

		case _StateString, _StateKey:
			switch {
			case b == '"':
				var ev Event
				if p.state == _StateKey {
					ev = KeyEnd
					p.state = _StateObjectColon
				} else {
					ev = StringEnd
					p.state = p.next()
				}
				return i + 1, ev
			case b == '\\':
				p.state++ // go to _State{String,Key}Escaped
			case b < 0x20:
				return i, p.error(`_StateString: @todo`)
			}

		case _StateStringEscaped, _StateKeyEscaped:
			switch b {
			case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
				p.state-- // back to _State{String,Key}
			case 'u':
				p.state = _StateStringUnicode
			default:
				return i, p.error(`_StateStringEscaped: @todo`)
			}

		case _StateNumberNegative:
			switch {
			case b == '0':
				p.state = _StateNumberZero
			case '1' <= b && b <= '9':
				p.state = _StateNumber
			default:
				return i, p.error(`_StateNumberNegative: @todo`)
			}

		case _StateNumber:
			if '0' <= b && b <= '9' {
				break
			}
			fallthrough

		case _StateNumberZero:
			switch b {
			case '.':
				p.state = _StateNumberDotFirstDigit
			case 'e', 'E':
				p.state = _StateNumberExpSign
			default:
				p.state = p.next()
				return i, NumberEnd // rewind (note: `i` instead of `i + 1`)
			}

		case _StateNumberDotFirstDigit:
			if b < '0' || b > '9' {
				return i, p.error(`_StateNumberDot: @todo`)
			}
			p.state++

		case _StateNumberDotDigit:
			switch {
			case b == 'e', b == 'E':
				p.state = _StateNumberExpSign
			case b < '0' || b > '9':
				return i, p.error(`_StateNumberDotDigit: @todo`)
			}

		case _StateNumberExpSign:
			p.state++
			if b == '+' || b == '-' {
				break
			}
			fallthrough

		case _StateNumberExpFirstDigit:
			if b < '0' || b > '9' {
				return i, p.error(`_StateNumberAfterExp: @todo`)
			}
			p.state++

		case _StateNumberExpDigit:
			if b < '0' || b > '9' {
				p.state = p.next()
				return i + 1, NumberEnd
			}

		case _StateTrue:
			if b != 'r' {
				return i, p.error(`_StateTrue: @todo`)
			}
			p.state++

		case _StateTrue2:
			if b != 'u' {
				return i, p.error(`_StateTrue2: @todo`)
			}
			p.state++

		case _StateTrue3:
			if b != 'e' {
				return i, p.error(`_StateTrue3: @todo`)
			}
			p.state = p.next()

			return i + 1, BoolEnd

		case _StateFalse:
			if b != 'a' {
				return i, p.error(`_StateFalse: @todo`)
			}
			p.state++

		case _StateFalse2:
			if b != 'l' {
				return i, p.error(`_StateFalse2: @todo`)
			}
			p.state++

		case _StateFalse3:
			if b != 's' {
				return i, p.error(`_StateFalse3: @todo`)
			}
			p.state++

		case _StateFalse4:
			if b != 'e' {
				return i, p.error(`_StateFalse4: @todo`)
			}
			p.state = p.next()

			return i + 1, BoolEnd

		case _StateNull:
			if b != 'u' {
				return i, p.error(`_StateNull: @todo`)
			}
			p.state++

		case _StateNull2:
			if b != 'l' {
				return i, p.error(`_StateNull2: @todo`)
			}
			p.state++

		case _StateNull3:
			if b != 'l' {
				return i, p.error(`_StateNull3: @todo`)
			}
			p.state = p.next()

			return i + 1, NullEnd

		case _StateDone:
			return i, p.error(`_StateDone: @todo`)

		default:
			panic(`invalid state`)
		}
	}

	return len(input), None
}

// Informs the parser not to expect any further input. Returns
// pending NumberEnd events if there are any, or a SyntaxError
// if EOF was not expected -- otherwise None.
func (p *Parser) Eof() Event {
	switch p.state {
	case _StateNumberZero,
		_StateNumber,
		_StateNumberDotDigit,
		_StateNumberExpDigit:
		p.state = _StateDone
		return NumberEnd
	case _StateDone:
		return None
	}
	return p.error(`.Eof(): @todo`)
}

// Pops the next state off the parser struct's queue.
func (p *Parser) next() int {
	length := len(p.queue)

	// with the "state queue" empty, we can only wait for EOF
	if length == 0 {
		return _StateDone
	}

	state := p.queue[length-1]
	p.queue = p.queue[:length-1]

	return state
}

// Insert a new state at the top of the queue.
func (p *Parser) push(state int) {
	p.queue = append(p.queue, state)
}

// Registers a syntax error. Always returns a SyntaxError event.
func (p *Parser) error(message string) Event {
	p.err = syntaxError(message)
	return SyntaxError
}
<commit_msg>Correct off-by-one error<commit_after>package jo

// Parsing events.
type Event int

const (
	None = iota
	SyntaxError

	ObjectStart
	ObjectEnd
	KeyStart
	KeyEnd
	ArrayStart
	ArrayEnd

	StringStart
	StringEnd
	NumberStart
	NumberEnd
	BoolStart
	BoolEnd
	NullStart
	NullEnd
)

// Parser states.
const (
	_StateValue = iota
	_StateDone

	_StateObjectKeyOrEnd   // {
	_StateObjectColon      // {"foo"
	_StateObjectCommaOrEnd // {"foo":"bar"

	_StateArrayValueOrEnd // [
	_StateArrayCommaOrEnd // ["any value"
	_StateArrayValue      // ["any value",

	// leading whitespace should be consumed from all states
	// above this line
	_AllowWhitespace

	_StateStringUnicode  // "\u
	_StateStringUnicode2 // "\u1
	_StateStringUnicode3 // "\u12
	_StateStringUnicode4 // "\u123
	_StateString         // "
	_StateStringEscaped  // "\

	_StateKeyUnicode  // "\u
	_StateKeyUnicode2 // "\u1
	_StateKeyUnicode3 // "\u12
	_StateKeyUnicode4 // "\u123
	_StateKey         // "
	_StateKeyEscaped  // "\

	_StateNumberNegative      // -
	_StateNumberZero          // 0
	_StateNumber              // 123
	_StateNumberDotFirstDigit // 123.
	_StateNumberDotDigit      // 123.4
	_StateNumberExpSign       // 123e
	_StateNumberExpFirstDigit // 123e+
	_StateNumberExpDigit      // 123e+1

	_StateTrue  // t
	_StateTrue2 // tr
	_StateTrue3 // tru

	_StateFalse  // f
	_StateFalse2 // fa
	_StateFalse3 // fal
	_StateFalse4 // fals

	_StateNull  // n
	_StateNull2 // nu
	_StateNull3 // nul

	_StateSyntaxError
)

// Our own little implementation of the `error` interface.
type syntaxError string

func (e syntaxError) Error() string {
	return string(e)
}

// Parser state machine.
type Parser struct {
	state int
	queue []int
	err   error
}

// Parses a byte slice containing JSON data. Returns the number of bytes
// read and an appropriate Event.
func (p *Parser) Parse(input []byte) (int, Event) {
	for i := 0; i < len(input); i++ {
		b := input[i]

		// optionally trim leading whitespace
		if p.state < _AllowWhitespace &&
			(b == ' ' || b == '\t' || b == '\n' || b == '\r') {
			continue
		}

		switch p.state {
		case _StateValue:
			switch {
			case b == '{':
				p.state = _StateObjectKeyOrEnd
				return i + 1, ObjectStart
			case b == '[':
				p.state = _StateArrayValueOrEnd
				return i + 1, ArrayStart
			case b == '"':
				p.state = _StateString
				return i + 1, StringStart
			case b == '-':
				p.state = _StateNumberNegative
				return i + 1, NumberStart
			case b == '0':
				p.state = _StateNumberZero
				return i + 1, NumberStart
			case '1' <= b && b <= '9':
				p.state = _StateNumber
				return i + 1, NumberStart
			case b == 't':
				p.state = _StateTrue
				return i + 1, BoolStart
			case b == 'f':
				p.state = _StateFalse
				return i + 1, BoolStart
			case b == 'n':
				p.state = _StateNull
				return i + 1, NullStart
			default:
				return i, p.error(`_StateValue: @todo`)
			}

		case _StateObjectKeyOrEnd:
			if b == '}' {
				p.state = p.next()
				return i + 1, ObjectEnd
			}
			if b != '"' {
				return i, p.error(`_StateObjectKeyOrEnd: @todo`)
			}

			p.state = _StateKey
			return i + 1, KeyStart

		case _StateObjectColon:
			if b != ':' {
				return i, p.error(`_StateObjectKeyOrEnd: @todo`)
			}

			p.push(_StateObjectCommaOrEnd)
			p.state = _StateValue

		case _StateObjectCommaOrEnd:
			switch b {
			case '}':
				p.state = p.next()
				return i + 1, ObjectEnd
			case ',':
				p.push(_StateObjectCommaOrEnd)
				p.state = _StateValue
			default:
				return i, p.error(`_StateObjectCommaOrEnd: @todo`)
			}

		case _StateArrayValueOrEnd:
			if b == ']' {
				p.state = p.next()
				return i + 1, ArrayEnd
			}

			p.push(_StateArrayCommaOrEnd)
			p.state = _StateValue
			i-- // rewind and let _StateValue do the parsing

		case _StateArrayCommaOrEnd:
			switch b {
			case ']':
				p.state = p.next()
				return i + 1, ArrayEnd
			case ',':
				p.push(_StateArrayCommaOrEnd)
				p.state = _StateValue
			default:
				return i, p.error(`_StateArrayCommaOrEnd: @todo`)
			}

		case _StateStringUnicode, _StateKeyUnicode,
			_StateStringUnicode2, _StateKeyUnicode2,
			_StateStringUnicode3, _StateKeyUnicode3,
			_StateStringUnicode4, _StateKeyUnicode4:
			switch {
			case '0' <= b && b <= '9':
			case 'a' <= b && b <= 'f':
			case 'A' <= b && b <= 'F':
			default:
				return i, p.error(`_StateStringUnicodeX: @todo`)
			}

			// note that _State{String,Key}Unicode4 + 1 == _State{String/Key}
			p.state++

		case _StateString, _StateKey:
			switch {
			case b == '"':
				var ev Event
				if p.state == _StateKey {
					ev = KeyEnd
					p.state = _StateObjectColon
				} else {
					ev = StringEnd
					p.state = p.next()
				}
				return i + 1, ev
			case b == '\\':
				p.state++ // go to _State{String,Key}Escaped
			case b < 0x20:
				return i, p.error(`_StateString: @todo`)
			}

		case _StateStringEscaped, _StateKeyEscaped:
			switch b {
			case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
				p.state-- // back to _State{String,Key}
			case 'u':
				p.state = _StateStringUnicode
			default:
				return i, p.error(`_StateStringEscaped: @todo`)
			}

		case _StateNumberNegative:
			switch {
			case b == '0':
				p.state = _StateNumberZero
			case '1' <= b && b <= '9':
				p.state = _StateNumber
			default:
				return i, p.error(`_StateNumberNegative: @todo`)
			}

		case _StateNumber:
			if '0' <= b && b <= '9' {
				break
			}
			fallthrough

		case _StateNumberZero:
			switch b {
			case '.':
				p.state = _StateNumberDotFirstDigit
			case 'e', 'E':
				p.state = _StateNumberExpSign
			default:
				p.state = p.next()
				return i, NumberEnd // rewind (note: `i` instead of `i + 1`)
			}

		case _StateNumberDotFirstDigit:
			if b < '0' || b > '9' {
				return i, p.error(`_StateNumberDot: @todo`)
			}
			p.state++

		case _StateNumberDotDigit:
			switch {
			case b == 'e', b == 'E':
				p.state = _StateNumberExpSign
			case b < '0' || b > '9':
				return i, p.error(`_StateNumberDotDigit: @todo`)
			}

		case _StateNumberExpSign:
			p.state++
			if b == '+' || b == '-' {
				break
			}
			fallthrough

		case _StateNumberExpFirstDigit:
			if b < '0' || b > '9' {
				return i, p.error(`_StateNumberAfterExp: @todo`)
			}
			p.state++

		case _StateNumberExpDigit:
			if b < '0' || b > '9' {
				p.state = p.next()
				return i, NumberEnd
			}

		case _StateTrue:
			if b != 'r' {
				return i, p.error(`_StateTrue: @todo`)
			}
			p.state++

		case _StateTrue2:
			if b != 'u' {
				return i, p.error(`_StateTrue2: @todo`)
			}
			p.state++

		case _StateTrue3:
			if b != 'e' {
				return i, p.error(`_StateTrue3: @todo`)
			}
			p.state = p.next()

			return i + 1, BoolEnd

		case _StateFalse:
			if b != 'a' {
				return i, p.error(`_StateFalse: @todo`)
			}
			p.state++

		case _StateFalse2:
			if b != 'l' {
				return i, p.error(`_StateFalse2: @todo`)
			}
			p.state++

		case _StateFalse3:
			if b != 's' {
				return i, p.error(`_StateFalse3: @todo`)
			}
			p.state++

		case _StateFalse4:
			if b != 'e' {
				return i, p.error(`_StateFalse4: @todo`)
			}
			p.state = p.next()

			return i + 1, BoolEnd

		case _StateNull:
			if b != 'u' {
				return i, p.error(`_StateNull: @todo`)
			}
			p.state++

		case _StateNull2:
			if b != 'l' {
				return i, p.error(`_StateNull2: @todo`)
			}
			p.state++

		case _StateNull3:
			if b != 'l' {
				return i, p.error(`_StateNull3: @todo`)
			}
			p.state = p.next()

			return i + 1, NullEnd

		case _StateDone:
			return i, p.error(`_StateDone: @todo`)

		default:
			panic(`invalid state`)
		}
	}

	return len(input), None
}

// Informs the parser not to expect any further input. Returns
// pending NumberEnd events if there are any, or a SyntaxError
// if EOF was not expected -- otherwise None.
func (p *Parser) Eof() Event {
	switch p.state {
	case _StateNumberZero,
		_StateNumber,
		_StateNumberDotDigit,
		_StateNumberExpDigit:
		p.state = _StateDone
		return NumberEnd
	case _StateDone:
		return None
	}
	return p.error(`.Eof(): @todo`)
}

// Pops the next state off the parser struct's queue.
func (p *Parser) next() int {
	length := len(p.queue)

	// with the "state queue" empty, we can only wait for EOF
	if length == 0 {
		return _StateDone
	}

	state := p.queue[length-1]
	p.queue = p.queue[:length-1]

	return state
}

// Insert a new state at the top of the queue.
func (p *Parser) push(state int) {
	p.queue = append(p.queue, state)
}

// Registers a syntax error. Always returns a SyntaxError event.
func (p *Parser) error(message string) Event {
	p.err = syntaxError(message)
	return SyntaxError
}
<|endoftext|>


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

// Mach-O header data structures
// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html

package macho

import "strconv"

// A FileHeader represents a Mach-O file header.
type FileHeader struct {
	Magic  uint32
	Cpu    Cpu
	SubCpu uint32
	Type   Type
	Ncmd   uint32
	Cmdsz  uint32
	Flags  uint32
}

const (
	fileHeaderSize32 = 7 * 4
	fileHeaderSize64 = 8 * 4
)

const (
	Magic32  uint32 = 0xfeedface
	Magic64  uint32 = 0xfeedfacf
	MagicFat uint32 = 0xcafebabe
)

// A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library.
type Type uint32

const (
	TypeObj    Type = 1
	TypeExec   Type = 2
	TypeDylib  Type = 6
	TypeBundle Type = 8
)

var typeStrings = []intName{
	{uint32(TypeObj), "Obj"},
	{uint32(TypeExec), "Exec"},
	{uint32(TypeDylib), "Dylib"},
	{uint32(TypeBundle), "Bundle"},
}

func (t Type) String() string   { return stringName(uint32(t), typeStrings, false) }
func (t Type) GoString() string { return stringName(uint32(t), typeStrings, true) }

// A Cpu is a Mach-O cpu type.
type Cpu uint32

const cpuArch64 = 0x01000000

const (
	Cpu386   Cpu = 7
	CpuAmd64 Cpu = Cpu386 | cpuArch64
	CpuArm   Cpu = 12
	CpuArm64 Cpu = CpuArm | cpuArch64
	CpuPpc   Cpu = 18
	CpuPpc64 Cpu = CpuPpc | cpuArch64
)

var cpuStrings = []intName{
	{uint32(Cpu386), "Cpu386"},
	{uint32(CpuAmd64), "CpuAmd64"},
	{uint32(CpuArm), "CpuArm"},
	{uint32(CpuArm64), "CpuArm64"},
	{uint32(CpuPpc), "CpuPpc"},
	{uint32(CpuPpc64), "CpuPpc64"},
}

func (i Cpu) String() string   { return stringName(uint32(i), cpuStrings, false) }
func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) }

// A LoadCmd is a Mach-O load command.
type LoadCmd uint32

const (
	LoadCmdSegment    LoadCmd = 0x1
	LoadCmdSymtab     LoadCmd = 0x2
	LoadCmdThread     LoadCmd = 0x4
	LoadCmdUnixThread LoadCmd = 0x5 // thread+stack
	LoadCmdDysymtab   LoadCmd = 0xb
	LoadCmdDylib      LoadCmd = 0xc // load dylib command
	LoadCmdDylinker   LoadCmd = 0xf // id dylinker command (not load dylinker command)
	LoadCmdSegment64  LoadCmd = 0x19
	LoadCmdRpath      LoadCmd = 0x8000001c
)

var cmdStrings = []intName{
	{uint32(LoadCmdSegment), "LoadCmdSegment"},
	{uint32(LoadCmdThread), "LoadCmdThread"},
	{uint32(LoadCmdUnixThread), "LoadCmdUnixThread"},
	{uint32(LoadCmdDylib), "LoadCmdDylib"},
	{uint32(LoadCmdSegment64), "LoadCmdSegment64"},
	{uint32(LoadCmdRpath), "LoadCmdRpath"},
}

func (i LoadCmd) String() string   { return stringName(uint32(i), cmdStrings, false) }
func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) }

type (
	// A Segment32 is a 32-bit Mach-O segment load command.
	Segment32 struct {
		Cmd     LoadCmd
		Len     uint32
		Name    [16]byte
		Addr    uint32
		Memsz   uint32
		Offset  uint32
		Filesz  uint32
		Maxprot uint32
		Prot    uint32
		Nsect   uint32
		Flag    uint32
	}

	// A Segment64 is a 64-bit Mach-O segment load command.
	Segment64 struct {
		Cmd     LoadCmd
		Len     uint32
		Name    [16]byte
		Addr    uint64
		Memsz   uint64
		Offset  uint64
		Filesz  uint64
		Maxprot uint32
		Prot    uint32
		Nsect   uint32
		Flag    uint32
	}

	// A SymtabCmd is a Mach-O symbol table command.
	SymtabCmd struct {
		Cmd     LoadCmd
		Len     uint32
		Symoff  uint32
		Nsyms   uint32
		Stroff  uint32
		Strsize uint32
	}

	// A DysymtabCmd is a Mach-O dynamic symbol table command.
	DysymtabCmd struct {
		Cmd            LoadCmd
		Len            uint32
		Ilocalsym      uint32
		Nlocalsym      uint32
		Iextdefsym     uint32
		Nextdefsym     uint32
		Iundefsym      uint32
		Nundefsym      uint32
		Tocoffset      uint32
		Ntoc           uint32
		Modtaboff      uint32
		Nmodtab        uint32
		Extrefsymoff   uint32
		Nextrefsyms    uint32
		Indirectsymoff uint32
		Nindirectsyms  uint32
		Extreloff      uint32
		Nextrel        uint32
		Locreloff      uint32
		Nlocrel        uint32
	}

	// A DylibCmd is a Mach-O load dynamic library command.
	DylibCmd struct {
		Cmd            LoadCmd
		Len            uint32
		Name           uint32
		Time           uint32
		CurrentVersion uint32
		CompatVersion  uint32
	}

	// A RpathCmd is a Mach-O rpath command.
	RpathCmd struct {
		Cmd  LoadCmd
		Len  uint32
		Path uint32
	}

	// A Thread is a Mach-O thread state command.
	Thread struct {
		Cmd  LoadCmd
		Len  uint32
		Type uint32
		Data []uint32
	}
)

const (
	FlagNoUndefs              uint32 = 0x1
	FlagIncrLink              uint32 = 0x2
	FlagDyldLink              uint32 = 0x4
	FlagBindAtLoad            uint32 = 0x8
	FlagPrebound              uint32 = 0x10
	FlagSplitSegs             uint32 = 0x20
	FlagLazyInit              uint32 = 0x40
	FlagTwoLevel              uint32 = 0x80
	FlagForceFlat             uint32 = 0x100
	FlagNoMultiDefs           uint32 = 0x200
	FlagNoFixPrebinding       uint32 = 0x400
	FlagPrebindable           uint32 = 0x800
	FlagAllModsBound          uint32 = 0x1000
	FlagSubsectionsViaSymbols uint32 = 0x2000
	FlagCanonical             uint32 = 0x4000
	FlagWeakDefines           uint32 = 0x8000
	FlagBindsToWeak           uint32 = 0x10000
	FlagAllowStackExecution   uint32 = 0x20000
	FlagRootSafe              uint32 = 0x40000
	FlagSetuidSafe            uint32 = 0x80000
	FlagNoReexportedDylibs    uint32 = 0x100000
	FlagPIE                   uint32 = 0x200000
	FlagDeadStrippableDylib   uint32 = 0x400000
	FlagHasTLVDescriptors     uint32 = 0x800000
	FlagNoHeapExecution       uint32 = 0x1000000
	FlagAppExtensionSafe      uint32 = 0x2000000
)

// A Section32 is a 32-bit Mach-O section header.
type Section32 struct {
	Name     [16]byte
	Seg      [16]byte
	Addr     uint32
	Size     uint32
	Offset   uint32
	Align    uint32
	Reloff   uint32
	Nreloc   uint32
	Flags    uint32
	Reserve1 uint32
	Reserve2 uint32
}

// A Section64 is a 64-bit Mach-O section header.
type Section64 struct {
	Name     [16]byte
	Seg      [16]byte
	Addr     uint64
	Size     uint64
	Offset   uint32
	Align    uint32
	Reloff   uint32
	Nreloc   uint32
	Flags    uint32
	Reserve1 uint32
	Reserve2 uint32
	Reserve3 uint32
}

// An Nlist32 is a Mach-O 32-bit symbol table entry.
type Nlist32 struct {
	Name  uint32
	Type  uint8
	Sect  uint8
	Desc  uint16
	Value uint32
}

// An Nlist64 is a Mach-O 64-bit symbol table entry.
type Nlist64 struct {
	Name  uint32
	Type  uint8
	Sect  uint8
	Desc  uint16
	Value uint64
}

// Regs386 is the Mach-O 386 register structure.
type Regs386 struct {
	AX    uint32
	BX    uint32
	CX    uint32
	DX    uint32
	DI    uint32
	SI    uint32
	BP    uint32
	SP    uint32
	SS    uint32
	FLAGS uint32
	IP    uint32
	CS    uint32
	DS    uint32
	ES    uint32
	FS    uint32
	GS    uint32
}

// RegsAMD64 is the Mach-O AMD64 register structure.
type RegsAMD64 struct {
	AX    uint64
	BX    uint64
	CX    uint64
	DX    uint64
	DI    uint64
	SI    uint64
	BP    uint64
	SP    uint64
	R8    uint64
	R9    uint64
	R10   uint64
	R11   uint64
	R12   uint64
	R13   uint64
	R14   uint64
	R15   uint64
	IP    uint64
	FLAGS uint64
	CS    uint64
	FS    uint64
	GS    uint64
}

type intName struct {
	i uint32
	s string
}

func stringName(i uint32, names []intName, goSyntax bool) string {
	for _, n := range names {
		if n.i == i {
			if goSyntax {
				return "macho." + n.s
			}
			return n.s
		}
	}
	return strconv.FormatUint(uint64(i), 10)
}
<commit_msg>cmd/link: fix stale link to MachO file format reference in comment<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Mach-O header data structures
// Originally at:
// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html (since deleted by Apply)
// Archived copy at:
// https://web.archive.org/web/20090819232456/http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/index.html
// For cloned PDF see:
// https://github.com/aidansteele/osx-abi-macho-file-format-reference

package macho

import "strconv"

// A FileHeader represents a Mach-O file header.
type FileHeader struct {
	Magic  uint32
	Cpu    Cpu
	SubCpu uint32
	Type   Type
	Ncmd   uint32
	Cmdsz  uint32
	Flags  uint32
}

const (
	fileHeaderSize32 = 7 * 4
	fileHeaderSize64 = 8 * 4
)

const (
	Magic32  uint32 = 0xfeedface
	Magic64  uint32 = 0xfeedfacf
	MagicFat uint32 = 0xcafebabe
)

// A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library.
type Type uint32

const (
	TypeObj    Type = 1
	TypeExec   Type = 2
	TypeDylib  Type = 6
	TypeBundle Type = 8
)

var typeStrings = []intName{
	{uint32(TypeObj), "Obj"},
	{uint32(TypeExec), "Exec"},
	{uint32(TypeDylib), "Dylib"},
	{uint32(TypeBundle), "Bundle"},
}

func (t Type) String() string   { return stringName(uint32(t), typeStrings, false) }
func (t Type) GoString() string { return stringName(uint32(t), typeStrings, true) }

// A Cpu is a Mach-O cpu type.
type Cpu uint32

const cpuArch64 = 0x01000000

const (
	Cpu386   Cpu = 7
	CpuAmd64 Cpu = Cpu386 | cpuArch64
	CpuArm   Cpu = 12
	CpuArm64 Cpu = CpuArm | cpuArch64
	CpuPpc   Cpu = 18
	CpuPpc64 Cpu = CpuPpc | cpuArch64
)

var cpuStrings = []intName{
	{uint32(Cpu386), "Cpu386"},
	{uint32(CpuAmd64), "CpuAmd64"},
	{uint32(CpuArm), "CpuArm"},
	{uint32(CpuArm64), "CpuArm64"},
	{uint32(CpuPpc), "CpuPpc"},
	{uint32(CpuPpc64), "CpuPpc64"},
}

func (i Cpu) String() string   { return stringName(uint32(i), cpuStrings, false) }
func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) }

// A LoadCmd is a Mach-O load command.
type LoadCmd uint32

const (
	LoadCmdSegment    LoadCmd = 0x1
	LoadCmdSymtab     LoadCmd = 0x2
	LoadCmdThread     LoadCmd = 0x4
	LoadCmdUnixThread LoadCmd = 0x5 // thread+stack
	LoadCmdDysymtab   LoadCmd = 0xb
	LoadCmdDylib      LoadCmd = 0xc // load dylib command
	LoadCmdDylinker   LoadCmd = 0xf // id dylinker command (not load dylinker command)
	LoadCmdSegment64  LoadCmd = 0x19
	LoadCmdRpath      LoadCmd = 0x8000001c
)

var cmdStrings = []intName{
	{uint32(LoadCmdSegment), "LoadCmdSegment"},
	{uint32(LoadCmdThread), "LoadCmdThread"},
	{uint32(LoadCmdUnixThread), "LoadCmdUnixThread"},
	{uint32(LoadCmdDylib), "LoadCmdDylib"},
	{uint32(LoadCmdSegment64), "LoadCmdSegment64"},
	{uint32(LoadCmdRpath), "LoadCmdRpath"},
}

func (i LoadCmd) String() string   { return stringName(uint32(i), cmdStrings, false) }
func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) }

type (
	// A Segment32 is a 32-bit Mach-O segment load command.
	Segment32 struct {
		Cmd     LoadCmd
		Len     uint32
		Name    [16]byte
		Addr    uint32
		Memsz   uint32
		Offset  uint32
		Filesz  uint32
		Maxprot uint32
		Prot    uint32
		Nsect   uint32
		Flag    uint32
	}

	// A Segment64 is a 64-bit Mach-O segment load command.
	Segment64 struct {
		Cmd     LoadCmd
		Len     uint32
		Name    [16]byte
		Addr    uint64
		Memsz   uint64
		Offset  uint64
		Filesz  uint64
		Maxprot uint32
		Prot    uint32
		Nsect   uint32
		Flag    uint32
	}

	// A SymtabCmd is a Mach-O symbol table command.
	SymtabCmd struct {
		Cmd     LoadCmd
		Len     uint32
		Symoff  uint32
		Nsyms   uint32
		Stroff  uint32
		Strsize uint32
	}

	// A DysymtabCmd is a Mach-O dynamic symbol table command.
	DysymtabCmd struct {
		Cmd            LoadCmd
		Len            uint32
		Ilocalsym      uint32
		Nlocalsym      uint32
		Iextdefsym     uint32
		Nextdefsym     uint32
		Iundefsym      uint32
		Nundefsym      uint32
		Tocoffset      uint32
		Ntoc           uint32
		Modtaboff      uint32
		Nmodtab        uint32
		Extrefsymoff   uint32
		Nextrefsyms    uint32
		Indirectsymoff uint32
		Nindirectsyms  uint32
		Extreloff      uint32
		Nextrel        uint32
		Locreloff      uint32
		Nlocrel        uint32
	}

	// A DylibCmd is a Mach-O load dynamic library command.
	DylibCmd struct {
		Cmd            LoadCmd
		Len            uint32
		Name           uint32
		Time           uint32
		CurrentVersion uint32
		CompatVersion  uint32
	}

	// A RpathCmd is a Mach-O rpath command.
	RpathCmd struct {
		Cmd  LoadCmd
		Len  uint32
		Path uint32
	}

	// A Thread is a Mach-O thread state command.
	Thread struct {
		Cmd  LoadCmd
		Len  uint32
		Type uint32
		Data []uint32
	}
)

const (
	FlagNoUndefs              uint32 = 0x1
	FlagIncrLink              uint32 = 0x2
	FlagDyldLink              uint32 = 0x4
	FlagBindAtLoad            uint32 = 0x8
	FlagPrebound              uint32 = 0x10
	FlagSplitSegs             uint32 = 0x20
	FlagLazyInit              uint32 = 0x40
	FlagTwoLevel              uint32 = 0x80
	FlagForceFlat             uint32 = 0x100
	FlagNoMultiDefs           uint32 = 0x200
	FlagNoFixPrebinding       uint32 = 0x400
	FlagPrebindable           uint32 = 0x800
	FlagAllModsBound          uint32 = 0x1000
	FlagSubsectionsViaSymbols uint32 = 0x2000
	FlagCanonical             uint32 = 0x4000
	FlagWeakDefines           uint32 = 0x8000
	FlagBindsToWeak           uint32 = 0x10000
	FlagAllowStackExecution   uint32 = 0x20000
	FlagRootSafe              uint32 = 0x40000
	FlagSetuidSafe            uint32 = 0x80000
	FlagNoReexportedDylibs    uint32 = 0x100000
	FlagPIE                   uint32 = 0x200000
	FlagDeadStrippableDylib   uint32 = 0x400000
	FlagHasTLVDescriptors     uint32 = 0x800000
	FlagNoHeapExecution       uint32 = 0x1000000
	FlagAppExtensionSafe      uint32 = 0x2000000
)

// A Section32 is a 32-bit Mach-O section header.
type Section32 struct {
	Name     [16]byte
	Seg      [16]byte
	Addr     uint32
	Size     uint32
	Offset   uint32
	Align    uint32
	Reloff   uint32
	Nreloc   uint32
	Flags    uint32
	Reserve1 uint32
	Reserve2 uint32
}

// A Section64 is a 64-bit Mach-O section header.
type Section64 struct {
	Name     [16]byte
	Seg      [16]byte
	Addr     uint64
	Size     uint64
	Offset   uint32
	Align    uint32
	Reloff   uint32
	Nreloc   uint32
	Flags    uint32
	Reserve1 uint32
	Reserve2 uint32
	Reserve3 uint32
}

// An Nlist32 is a Mach-O 32-bit symbol table entry.
type Nlist32 struct {
	Name  uint32
	Type  uint8
	Sect  uint8
	Desc  uint16
	Value uint32
}

// An Nlist64 is a Mach-O 64-bit symbol table entry.
type Nlist64 struct {
	Name  uint32
	Type  uint8
	Sect  uint8
	Desc  uint16
	Value uint64
}

// Regs386 is the Mach-O 386 register structure.
type Regs386 struct {
	AX    uint32
	BX    uint32
	CX    uint32
	DX    uint32
	DI    uint32
	SI    uint32
	BP    uint32
	SP    uint32
	SS    uint32
	FLAGS uint32
	IP    uint32
	CS    uint32
	DS    uint32
	ES    uint32
	FS    uint32
	GS    uint32
}

// RegsAMD64 is the Mach-O AMD64 register structure.
type RegsAMD64 struct {
	AX    uint64
	BX    uint64
	CX    uint64
	DX    uint64
	DI    uint64
	SI    uint64
	BP    uint64
	SP    uint64
	R8    uint64
	R9    uint64
	R10   uint64
	R11   uint64
	R12   uint64
	R13   uint64
	R14   uint64
	R15   uint64
	IP    uint64
	FLAGS uint64
	CS    uint64
	FS    uint64
	GS    uint64
}

type intName struct {
	i uint32
	s string
}

func stringName(i uint32, names []intName, goSyntax bool) string {
	for _, n := range names {
		if n.i == i {
			if goSyntax {
				return "macho." + n.s
			}
			return n.s
		}
	}
	return strconv.FormatUint(uint64(i), 10)
}
<|endoftext|>


<commit_before>package mc

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"os"
	"sync"
)

// Errors
var (
	ErrNotFound       = os.NewError("mc: not found")
	ErrKeyExists      = os.NewError("mc: key exists")
	ErrValueTooLarge  = os.NewError("mc: value to large")
	ErrInvalidArgs    = os.NewError("mc: invalid arguments")
	ErrValueNotStored = os.NewError("mc: value not stored")
	ErrNonNumeric     = os.NewError("mc: incr/decr called on non-numeric value")
	ErrAuthRequired   = os.NewError("mc: authentication required")
	ErrUnknownCommand = os.NewError("mc: unknown command")
	ErrOutOfMemory    = os.NewError("mc: out of memory")
)

var errMap = map[uint16]os.Error{
	0:    nil,
	1:    ErrNotFound,
	2:    ErrKeyExists,
	3:    ErrValueTooLarge,
	4:    ErrInvalidArgs,
	5:    ErrValueNotStored,
	6:    ErrNonNumeric,
	0x20: ErrAuthRequired,
	0x81: ErrUnknownCommand,
	0x82: ErrOutOfMemory,
}

// Ops
const (
	OpGet = uint8(iota)
	OpSet
	OpAdd
	OpReplace
	OpDelete
	OpIncrement
	OpDecrement
	OpQuit
	OpFlush
	OpGetQ
	OpNoop
	OpVersion
	OpGetK
	OpGetKQ
	OpAppend
	OpPrepend
	OpStat
	OpSetQ
	OpAddQ
	OpReplaceQ
	OpDeleteQ
	OpIncrementQ
	OpDecrementQ
	OpQuitQ
	OpFlushQ
	OpAppendQ
	OpPrependQ
)

type header struct {
	Magic        uint8
	Op           uint8
	KeyLen       uint16
	ExtraLen     uint8
	DataType     uint8
	ResvOrStatus uint16
	BodyLen      uint32
	Opaque       uint32
	CAS          uint64
}

type body struct {
	iextras []interface{}
	oextras []interface{}
	key     string
	val     string
}

type Conn struct {
	rwc io.ReadWriteCloser
	l   sync.Mutex
}

func Dial(addr string) (*Conn, os.Error) {
	nc, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}

	cn := &Conn{rwc: nc}
	return cn, nil
}

func (cn *Conn) Get(key string) (val string, cas int, err os.Error) {
	h := &header{
		Op: OpGet,
	}

	b := &body{
		key: key,
	}

	err = cn.send(h, b)

	return b.val, int(h.CAS), err
}

func (cn *Conn) Set(key, val string, ocas, flags, exp int) os.Error {
	h := &header{
		Op:  OpSet,
		CAS: uint64(ocas),
	}

	b := &body{
		iextras: []interface{}{uint32(flags), uint32(exp)},
		key:     key,
		val:     val,
	}

	return cn.send(h, b)
}

func (cn *Conn) Del(key string) os.Error {
	h := &header{
		Op: OpDelete,
	}

	b := &body{
		key: key,
	}

	return cn.send(h, b)
}

func (cn *Conn) send(h *header, b *body) (err os.Error) {
	const magic uint8 = 0x80

	h.Magic = magic
	h.ExtraLen = sizeOfExtras(b.iextras)
	h.KeyLen = uint16(len(b.key))
	h.BodyLen = uint32(h.ExtraLen) + uint32(h.KeyLen) + uint32(len(b.val))

	cn.l.Lock()
	defer cn.l.Unlock()

	// Request
	err = binary.Write(cn.rwc, binary.BigEndian, h)
	if err != nil {
		return
	}

	for _, e := range b.iextras {
		err = binary.Write(cn.rwc, binary.BigEndian, e)
		if err != nil {
			return
		}
	}

	_, err = io.WriteString(cn.rwc, b.key)
	if err != nil {
		return
	}

	_, err = io.WriteString(cn.rwc, b.val)
	if err != nil {
		return
	}

	// Response
	err = binary.Read(cn.rwc, binary.BigEndian, h)
	if err != nil {
		return err
	}

	serr := checkError(h)

	for _, e := range b.oextras {
		err = binary.Read(cn.rwc, binary.BigEndian, e)
		if err != nil {
			return
		}
	}

	b.key, err = cn.readString(uint(h.KeyLen))
	if err != nil {
		return
	}

	vlen := uint(h.BodyLen) - uint(h.ExtraLen) - uint(h.KeyLen)
	b.val, err = cn.readString(vlen)
	if err != nil {
		return
	}

	return serr
}

func (cn *Conn) readString(n uint) (string, os.Error) {
	b := make([]byte, n)
	_, err := io.ReadFull(cn.rwc, b)
	if err != nil {
		return "", err
	}
	return string(b), nil
}

func checkError(h *header) os.Error {
	err, ok := errMap[h.ResvOrStatus]
	if !ok {
		fmt.Printf("status: %d\n", h.ResvOrStatus)
		return os.NewError("mc: unknown error from server")
	}
	return err
}

func sizeOfExtras(extras []interface{}) (l uint8) {
	for _, e := range extras {
		switch e.(type) {
		default:
			panic(fmt.Sprintf("mc: unknown extra type (%T)", e))
		case uint8:
			l += 8 / 8
		case uint16:
			l += 16 / 8
		case uint32:
			l += 32 / 8
		case uint64:
			l += 64 / 8
		}
	}
	return
}
<commit_msg>checkError at end, not before<commit_after>package mc

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"os"
	"sync"
)

// Errors
var (
	ErrNotFound       = os.NewError("mc: not found")
	ErrKeyExists      = os.NewError("mc: key exists")
	ErrValueTooLarge  = os.NewError("mc: value to large")
	ErrInvalidArgs    = os.NewError("mc: invalid arguments")
	ErrValueNotStored = os.NewError("mc: value not stored")
	ErrNonNumeric     = os.NewError("mc: incr/decr called on non-numeric value")
	ErrAuthRequired   = os.NewError("mc: authentication required")
	ErrUnknownCommand = os.NewError("mc: unknown command")
	ErrOutOfMemory    = os.NewError("mc: out of memory")
)

var errMap = map[uint16]os.Error{
	0:    nil,
	1:    ErrNotFound,
	2:    ErrKeyExists,
	3:    ErrValueTooLarge,
	4:    ErrInvalidArgs,
	5:    ErrValueNotStored,
	6:    ErrNonNumeric,
	0x20: ErrAuthRequired,
	0x81: ErrUnknownCommand,
	0x82: ErrOutOfMemory,
}

// Ops
const (
	OpGet = uint8(iota)
	OpSet
	OpAdd
	OpReplace
	OpDelete
	OpIncrement
	OpDecrement
	OpQuit
	OpFlush
	OpGetQ
	OpNoop
	OpVersion
	OpGetK
	OpGetKQ
	OpAppend
	OpPrepend
	OpStat
	OpSetQ
	OpAddQ
	OpReplaceQ
	OpDeleteQ
	OpIncrementQ
	OpDecrementQ
	OpQuitQ
	OpFlushQ
	OpAppendQ
	OpPrependQ
)

type header struct {
	Magic        uint8
	Op           uint8
	KeyLen       uint16
	ExtraLen     uint8
	DataType     uint8
	ResvOrStatus uint16
	BodyLen      uint32
	Opaque       uint32
	CAS          uint64
}

type body struct {
	iextras []interface{}
	oextras []interface{}
	key     string
	val     string
}

type Conn struct {
	rwc io.ReadWriteCloser
	l   sync.Mutex
}

func Dial(addr string) (*Conn, os.Error) {
	nc, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}

	cn := &Conn{rwc: nc}
	return cn, nil
}

func (cn *Conn) Get(key string) (val string, cas int, err os.Error) {
	h := &header{
		Op: OpGet,
	}

	b := &body{
		key: key,
	}

	err = cn.send(h, b)

	return b.val, int(h.CAS), err
}

func (cn *Conn) Set(key, val string, ocas, flags, exp int) os.Error {
	h := &header{
		Op:  OpSet,
		CAS: uint64(ocas),
	}

	b := &body{
		iextras: []interface{}{uint32(flags), uint32(exp)},
		key:     key,
		val:     val,
	}

	return cn.send(h, b)
}

func (cn *Conn) Del(key string) os.Error {
	h := &header{
		Op: OpDelete,
	}

	b := &body{
		key: key,
	}

	return cn.send(h, b)
}

func (cn *Conn) send(h *header, b *body) (err os.Error) {
	const magic uint8 = 0x80

	h.Magic = magic
	h.ExtraLen = sizeOfExtras(b.iextras)
	h.KeyLen = uint16(len(b.key))
	h.BodyLen = uint32(h.ExtraLen) + uint32(h.KeyLen) + uint32(len(b.val))

	cn.l.Lock()
	defer cn.l.Unlock()

	// Request
	err = binary.Write(cn.rwc, binary.BigEndian, h)
	if err != nil {
		return
	}

	for _, e := range b.iextras {
		err = binary.Write(cn.rwc, binary.BigEndian, e)
		if err != nil {
			return
		}
	}

	_, err = io.WriteString(cn.rwc, b.key)
	if err != nil {
		return
	}

	_, err = io.WriteString(cn.rwc, b.val)
	if err != nil {
		return
	}

	// Response
	err = binary.Read(cn.rwc, binary.BigEndian, h)
	if err != nil {
		return err
	}

	for _, e := range b.oextras {
		err = binary.Read(cn.rwc, binary.BigEndian, e)
		if err != nil {
			return
		}
	}

	b.key, err = cn.readString(uint(h.KeyLen))
	if err != nil {
		return
	}

	vlen := uint(h.BodyLen) - uint(h.ExtraLen) - uint(h.KeyLen)
	b.val, err = cn.readString(vlen)
	if err != nil {
		return
	}

	return checkError(h)
}

func (cn *Conn) readString(n uint) (string, os.Error) {
	b := make([]byte, n)
	_, err := io.ReadFull(cn.rwc, b)
	if err != nil {
		return "", err
	}
	return string(b), nil
}

func checkError(h *header) os.Error {
	err, ok := errMap[h.ResvOrStatus]
	if !ok {
		fmt.Printf("status: %d\n", h.ResvOrStatus)
		return os.NewError("mc: unknown error from server")
	}
	return err
}

func sizeOfExtras(extras []interface{}) (l uint8) {
	for _, e := range extras {
		switch e.(type) {
		default:
			panic(fmt.Sprintf("mc: unknown extra type (%T)", e))
		case uint8:
			l += 8 / 8
		case uint16:
			l += 16 / 8
		case uint32:
			l += 32 / 8
		case uint64:
			l += 64 / 8
		}
	}
	return
}
<|endoftext|>


<commit_before>/**
 * Copyright 2014 @ z3q.net.
 * name :
 * author : jarryliu
 * date : 2013-12-03 23:20
 * description :
 * history :
 */
package query

import (
	"database/sql"
	"fmt"
	"github.com/jsix/gof/db"
	"github.com/jsix/gof/log"
	"go2o/core/domain/interface/member"
	"go2o/core/dto"
	"go2o/core/infrastructure/domain"
	"go2o/core/infrastructure/format"
	"strconv"
	"strings"
)

type MemberQuery struct {
	db.Connector
}

func NewMemberQuery(c db.Connector) *MemberQuery {
	return &MemberQuery{c}
}

// 获取会员列表
func (m *MemberQuery) GetMemberList(ids []int) []*dto.MemberSummary {
	list := []*dto.MemberSummary{}
	strIds := make([]string, len(ids))
	for i, v := range ids {
		strIds[i] = strconv.Itoa(v)
	}
	if len(ids) > 0 {
		inStr := strings.Join(strIds, ",") // order by field(field,val1,val2,val3)按IN的顺序排列
		query := fmt.Sprintf(`SELECT m.id,m.usr,m.name,m.avatar,m.exp,m.level,
				lv.name as level_name,a.integral,a.balance,a.present_balance,
				a.grow_balance,a.grow_amount,a.grow_earnings,a.grow_total_earnings,
				m.update_time FROM mm_member m INNER JOIN mm_level lv
				ON m.level = lv.id INNER JOIN mm_account a ON
				 a.member_id = m.id AND m.id IN(%s) order by field(m.id,%s)`, inStr, inStr)
		m.Connector.GetOrm().SelectByQuery(&list, query)
	}
	return list
}

// 获取账户余额分页记录
func (m *MemberQuery) PagedBalanceAccountLog(memberId, begin, end int,
	where, orderBy string) (num int, rows []map[string]interface{}) {
	d := m.Connector
	if orderBy != "" {
		orderBy = "ORDER BY " + orderBy
	}
	d.ExecScalar(fmt.Sprintf(`SELECT COUNT(0) FROM mm_balance_log bi
	 	INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE bi.member_id=? %s`, where), &num, memberId)

	sqlLine := fmt.Sprintf(`SELECT bi.* FROM mm_balance_log bi
			INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE member_id=? %s %s LIMIT ?,?`,
		where, orderBy)

	d.Query(sqlLine, func(_rows *sql.Rows) {
		rows = db.RowsToMarshalMap(_rows)
		_rows.Close()
	}, memberId, begin, end-begin)

	return num, rows
}

// 获取账户余额分页记录
func (m *MemberQuery) PagedPresentAccountLog(memberId, begin, end int,
	where, orderBy string) (num int, rows []map[string]interface{}) {
	d := m.Connector
	if orderBy != "" {
		orderBy = "ORDER BY " + orderBy
	}
	d.ExecScalar(fmt.Sprintf(`SELECT COUNT(0) FROM mm_present_log bi
	 	INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE bi.member_id=? %s`, where), &num, memberId)

	if num > 0 {
		sqlLine := fmt.Sprintf(`SELECT bi.* FROM mm_present_log bi
			INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE member_id=? %s %s LIMIT ?,?`,
			where, orderBy)

		d.Query(sqlLine, func(_rows *sql.Rows) {
			rows = db.RowsToMarshalMap(_rows)
			_rows.Close()
		}, memberId, begin, end-begin)
	} else {
		rows = []map[string]interface{}{}
	}

	return num, rows
}

// 获取返现记录
func (m *MemberQuery) QueryBalanceLog(memberId, begin, end int,
	where, orderBy string) (num int, rows []map[string]interface{}) {

	d := m.Connector

	if orderBy != "" {
		orderBy = "ORDER BY " + orderBy
	}
	d.ExecScalar(fmt.Sprintf(`SELECT COUNT(0) FROM mm_balance_info bi
	 	INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE bi.member_id=? %s`, where), &num, memberId)

	sqlLine := fmt.Sprintf(`SELECT bi.* FROM mm_balance_info bi
			INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE member_id=? %s %s LIMIT ?,?`,
		where, orderBy)

	d.Query(sqlLine, func(_rows *sql.Rows) {
		rows = db.RowsToMarshalMap(_rows)
		_rows.Close()
	}, memberId, begin, end-begin)

	return num, rows
}

// 获取最近的余额变动信息
func (m *MemberQuery) GetLatestBalanceInfoByKind(memberId int, kind int) *member.BalanceInfo {
	var info = new(member.BalanceInfo)
	if err := m.GetOrm().GetBy(info, "member_id=? AND kind=? ORDER BY create_time DESC",
		memberId, kind); err == nil {
		return info
	}
	return nil
}

// 筛选会员根据用户或者手机
func (m *MemberQuery) FilterMemberByUsrOrPhone(key string) []*dto.SimpleMember {
	qp := "%" + key + "%"
	var list []*dto.SimpleMember = make([]*dto.SimpleMember, 0)
	var id int
	var usr, name, phone, avatar string
	m.Query(`SELECT id,usr,mm_profile.name,mm_profile.phone,
        mm_profile.avatar FROM mm_member
        INNER JOIN mm_profile ON mm_profile.member_id=mm_member.id
        WHERE usr LIKE ? OR mm_profile.name LIKE ? OR
        mm_profile.phone LIKE ?`, func(rows *sql.Rows) {
		for rows.Next() {
			rows.Scan(&id, &usr, &name, &phone, &avatar)
			list = append(list, &dto.SimpleMember{
				Id:     id,
				User:   usr,
				Name:   name,
				Phone:  phone,
				Avatar: format.GetResUrl(avatar),
			})
		}
	}, qp, qp, qp)
	return list
}

func (m *MemberQuery) GetMemberByUsrOrPhone(key string) *dto.SimpleMember {
	e := dto.SimpleMember{}
	err := m.QueryRow(`SELECT id,usr,mm_profile.name,mm_profile.phone,
        mm_profile.avatar FROM mm_member
        INNER JOIN mm_profile ON mm_profile.member_id=mm_member.id
        WHERE usr = ? OR mm_profile.phone = ?`, func(rows *sql.Row) {
		rows.Scan(&e.Id, &e.User, &e.Name, &e.Phone, &e.Avatar)
		e.Avatar = format.GetResUrl(e.Avatar)
	}, key, key)
	if err == nil {
		return &e
	}
	return nil
}

// 根据手机获取会员编号
func (m *MemberQuery) GetMemberIdByPhone(phone string) int {
	id := 0
	m.ExecScalar(`SELECT id FROM mm_member
        INNER JOIN mm_profile ON mm_profile.member_id=mm_member.id
        WHERE mm_profile.phone = ? LIMIT 0,1`, &id, phone)
	return id
}

// 会员推广排名
func (m *MemberQuery) GetMemberInviRank(merchantId int, allTeam bool, levelComp string, level int,
	startTime int64, endTime int64, num int) []*dto.RankMember {
	var list []*dto.RankMember = make([]*dto.RankMember, 0)
	var id int
	var usr, name string
	var inviNum, totalNum, regTime int
	var rank int = 0

	var sortField string = "t.all_num DESC"
	if !allTeam {
		sortField = "t.invi_num DESC"
	}

	var levelCompStr string = fmt.Sprintf("%s%d", levelComp, level)
	//{level_comp}{level_value}

	m.Query(fmt.Sprintf(`SELECT id,usr,name,invi_num,all_num,reg_time FROM ( SELECT m.*,
 (SELECT COUNT(0) FROM mm_relation r INNER JOIN mm_member m1 ON m1.id = r.member_id WHERE
  (m1.level%s) AND r.invi_member_id = m.id
	AND r.reg_merchant_id=rl.reg_merchant_id  AND m1.reg_time BETWEEN
  ? AND ? ) as invi_num,
	((SELECT COUNT(0) FROM mm_relation r INNER JOIN mm_member m1 ON m1.id = r.member_id WHERE
  (m1.level%s) AND r.invi_member_id = m.id
	AND r.reg_merchant_id=rl.reg_merchant_id AND m1.reg_time BETWEEN
  ? AND ? )+
 (SELECT COUNT(0) FROM mm_relation r INNER JOIN mm_member m1
  ON m1.id = r.member_id WHERE (m1.level%s) AND invi_member_id IN
	(SELECT member_id FROM mm_relation r INNER JOIN mm_member m1 ON m1.id = r.member_id WHERE
  (m1.level%s) AND r.invi_member_id =
    m.id AND r.reg_merchant_id=rl.reg_merchant_id AND m1.reg_time BETWEEN
  ? AND ? ))) as all_num
 FROM mm_member m INNER JOIN mm_relation rl ON m.id= rl.member_id
 WHERE rl.reg_merchant_id = ? AND state= ?) t ORDER BY %s,t.reg_time asc
 LIMIT 0,?`, levelCompStr, levelCompStr, levelCompStr, levelCompStr, sortField), func(rows *sql.Rows) {
		for rows.Next() {
			rows.Scan(&id, &usr, &name, &inviNum, &totalNum, &regTime)
			rank++
			list = append(list, &dto.RankMember{
				Id:       id,
				Usr:      usr,
				Name:     name,
				RankNum:  rank,
				InviNum:  inviNum,
				TotalNum: totalNum,
				RegTime:  regTime,
			})
		}
	}, startTime, endTime, startTime, endTime, startTime, endTime, merchantId, 1, num)

	return list
}

// 查询有邀请关系的会员数量
func (m *MemberQuery) GetReferNum(memberId int, layer int) int {
	total := 0
	keyword := fmt.Sprintf("''r%d'':%d", layer, memberId)
	where := "refer_str LIKE '%" + keyword +
		",%' OR refer_str LIKE '%" + keyword + "}'"
	log.Println("SELECT COUNT(0) FROM mm_relation WHERE " + where)
	err := m.ExecScalar("SELECT COUNT(0) FROM mm_relation WHERE "+where, &total)
	if err != nil {
		domain.HandleError(err, "[ Go2o][ Member][ Query]:")
	}
	return total
}

// 获取分页商铺收藏
func (m *MemberQuery) PagedShopFav(memberId int, begin, end int,
	where string) (num int, rows []*dto.PagedShopFav) {
	d := m.Connector
	if len(where) > 0 {
		where = " AND " + where
	}
	d.ExecScalar(fmt.Sprintf(`SELECT COUNT(0) FROM mm_favorite f
	INNER JOIN  mch_shop s ON f.refer_id =s.id
    INNER JOIN mch_online_shop o ON s.id = o.shop_id
    INNER JOIN mch_merchant mch ON mch.id = s.mch_id
    WHERE f.member_id=? AND f.fav_type=? %s`, where), &num,
		memberId, member.FavTypeShop)

	if num > 0 {
		sqlLine := fmt.Sprintf(`SELECT f.id,s.id as shop_id,mch.id as mch_id,
    s.name as shop_name,o.logo,f.update_time FROM mm_favorite f
    INNER JOIN  mch_shop s ON f.refer_id =s.id
    INNER JOIN mch_online_shop o ON s.id = o.shop_id
    INNER JOIN mch_merchant mch ON mch.id = s.mch_id
    WHERE f.member_id=? AND f.fav_type=? %s ORDER BY f.update_time DESC LIMIT ?,?`,
			where)
		d.Query(sqlLine, func(rs *sql.Rows) {
			for rs.Next() {
				e := dto.PagedShopFav{}
				rs.Scan(&e.Id, &e.ShopId, &e.MchId, &e.ShopName,
					&e.Logo, &e.UpdateTime)
				e.Logo = format.GetResUrl(e.Logo)
				rows = append(rows, &e)
			}
		}, memberId, member.FavTypeShop, begin, end-begin)
	} else {
		rows = make([]*dto.PagedShopFav, 0)
	}
	return num, rows
}

// 获取分页商铺收藏
func (m *MemberQuery) PagedGoodsFav(memberId int, begin, end int,
	where string) (num int, rows []*dto.PagedGoodsFav) {
	d := m.Connector
	if len(where) > 0 {
		where = " AND " + where
	}
	d.ExecScalar(fmt.Sprintf(`SELECT COUNT(0) FROM mm_favorite f
    INNER JOIN gs_goods gs ON gs.id = f.refer_id
    INNER JOIN gs_item item ON gs.item_id=item.id
    WHERE f.member_id=? AND f.fav_type=? %s`, where), &num,
		memberId, member.FavTypeGoods)

	if num > 0 {
		sqlLine := fmt.Sprintf(`SELECT f.id,gs.id as goods_id,item.name as goods_name,
            img,sale_price,gs.stock_num,item.update_time
            FROM mm_favorite f INNER JOIN gs_goods gs ON gs.id = f.refer_id
            INNER JOIN gs_item item ON gs.item_id=item.id
            WHERE f.member_id=? AND f.fav_type=? %s ORDER BY f.update_time DESC
            LIMIT ?,?`,
			where)
		d.Query(sqlLine, func(rs *sql.Rows) {
			for rs.Next() {
				e := dto.PagedGoodsFav{}
				rs.Scan(&e.Id, &e.SkuId, &e.GoodsName, &e.Image, &e.SalePrice,
					&e.OnShelves, &e.StockNum, &e.UpdateTime)
				e.Image = format.GetResUrl(e.Image)
				rows = append(rows, &e)
			}
		}, memberId, member.FavTypeGoods, begin, end-begin)

	} else {
		rows = make([]*dto.PagedGoodsFav, 0)
	}
	return num, rows
}
<commit_msg>member query<commit_after>/**
 * Copyright 2014 @ z3q.net.
 * name :
 * author : jarryliu
 * date : 2013-12-03 23:20
 * description :
 * history :
 */
package query

import (
	"database/sql"
	"fmt"
	"github.com/jsix/gof/db"
	"github.com/jsix/gof/log"
	"go2o/core/domain/interface/member"
	"go2o/core/dto"
	"go2o/core/infrastructure/domain"
	"go2o/core/infrastructure/format"
	"strconv"
	"strings"
)

type MemberQuery struct {
	db.Connector
}

func NewMemberQuery(c db.Connector) *MemberQuery {
	return &MemberQuery{c}
}

// 获取会员列表
func (m *MemberQuery) GetMemberList(ids []int) []*dto.MemberSummary {
	list := []*dto.MemberSummary{}
	strIds := make([]string, len(ids))
	for i, v := range ids {
		strIds[i] = strconv.Itoa(v)
	}
	if len(ids) > 0 {
		inStr := strings.Join(strIds, ",") // order by field(field,val1,val2,val3)按IN的顺序排列
		query := fmt.Sprintf(`SELECT m.id,m.usr,m.name,m.avatar,m.exp,m.level,
				lv.name as level_name,a.integral,a.balance,a.present_balance,
				a.grow_balance,a.grow_amount,a.grow_earnings,a.grow_total_earnings,
				m.update_time FROM mm_member m INNER JOIN mm_level lv
				ON m.level = lv.id INNER JOIN mm_account a ON
				 a.member_id = m.id AND m.id IN(%s) order by field(m.id,%s)`, inStr, inStr)
		m.Connector.GetOrm().SelectByQuery(&list, query)
	}
	return list
}

// 获取账户余额分页记录
func (m *MemberQuery) PagedBalanceAccountLog(memberId, begin, end int,
	where, orderBy string) (num int, rows []map[string]interface{}) {
	d := m.Connector
	if orderBy != "" {
		orderBy = "ORDER BY " + orderBy
	}
	d.ExecScalar(fmt.Sprintf(`SELECT COUNT(0) FROM mm_balance_log bi
	 	INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE bi.member_id=? %s`, where), &num, memberId)

	sqlLine := fmt.Sprintf(`SELECT bi.* FROM mm_balance_log bi
			INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE member_id=? %s %s LIMIT ?,?`,
		where, orderBy)

	d.Query(sqlLine, func(_rows *sql.Rows) {
		rows = db.RowsToMarshalMap(_rows)
		_rows.Close()
	}, memberId, begin, end-begin)

	return num, rows
}

// 获取账户余额分页记录
func (m *MemberQuery) PagedPresentAccountLog(memberId, begin, end int,
	where, orderBy string) (num int, rows []map[string]interface{}) {
	d := m.Connector
	if orderBy != "" {
		orderBy = "ORDER BY " + orderBy
	}
	d.ExecScalar(fmt.Sprintf(`SELECT COUNT(0) FROM mm_present_log bi
	 	INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE bi.member_id=? %s`, where), &num, memberId)

	if num > 0 {
		sqlLine := fmt.Sprintf(`SELECT bi.* FROM mm_present_log bi
			INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE member_id=? %s %s LIMIT ?,?`,
			where, orderBy)

		d.Query(sqlLine, func(_rows *sql.Rows) {
			rows = db.RowsToMarshalMap(_rows)
			_rows.Close()
		}, memberId, begin, end-begin)
	} else {
		rows = []map[string]interface{}{}
	}

	return num, rows
}

// 获取返现记录
func (m *MemberQuery) QueryBalanceLog(memberId, begin, end int,
	where, orderBy string) (num int, rows []map[string]interface{}) {

	d := m.Connector

	if orderBy != "" {
		orderBy = "ORDER BY " + orderBy
	}
	d.ExecScalar(fmt.Sprintf(`SELECT COUNT(0) FROM mm_balance_info bi
	 	INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE bi.member_id=? %s`, where), &num, memberId)

	sqlLine := fmt.Sprintf(`SELECT bi.* FROM mm_balance_info bi
			INNER JOIN mm_member m ON m.id=bi.member_id
			WHERE member_id=? %s %s LIMIT ?,?`,
		where, orderBy)

	d.Query(sqlLine, func(_rows *sql.Rows) {
		rows = db.RowsToMarshalMap(_rows)
		_rows.Close()
	}, memberId, begin, end-begin)

	return num, rows
}

// 获取最近的余额变动信息
func (m *MemberQuery) GetLatestBalanceInfoByKind(memberId int, kind int) *member.BalanceInfo {
	var info = new(member.BalanceInfo)
	if err := m.GetOrm().GetBy(info, "member_id=? AND kind=? ORDER BY create_time DESC",
		memberId, kind); err == nil {
		return info
	}
	return nil
}

// 筛选会员根据用户或者手机
func (m *MemberQuery) FilterMemberByUsrOrPhone(key string) []*dto.SimpleMember {
	qp := "%" + key + "%"
	var list []*dto.SimpleMember = make([]*dto.SimpleMember, 0)
	var id int
	var usr, name, phone, avatar string
	m.Query(`SELECT id,usr,mm_profile.name,mm_profile.phone,
        mm_profile.avatar FROM mm_member
        INNER JOIN mm_profile ON mm_profile.member_id=mm_member.id
        WHERE usr LIKE ? OR mm_profile.name LIKE ? OR
        mm_profile.phone LIKE ?`, func(rows *sql.Rows) {
		for rows.Next() {
			rows.Scan(&id, &usr, &name, &phone, &avatar)
			list = append(list, &dto.SimpleMember{
				Id:     id,
				User:   usr,
				Name:   name,
				Phone:  phone,
				Avatar: format.GetResUrl(avatar),
			})
		}
	}, qp, qp, qp)
	return list
}

func (m *MemberQuery) GetMemberByUsrOrPhone(key string) *dto.SimpleMember {
	e := dto.SimpleMember{}
	err := m.QueryRow(`SELECT id,usr,mm_profile.name,mm_profile.phone,
        mm_profile.avatar FROM mm_member
        INNER JOIN mm_profile ON mm_profile.member_id=mm_member.id
        WHERE usr = ? OR mm_profile.phone = ?`, func(rows *sql.Row) {
		rows.Scan(&e.Id, &e.User, &e.Name, &e.Phone, &e.Avatar)
		e.Avatar = format.GetResUrl(e.Avatar)
	}, key, key)
	if err == nil {
		return &e
	}
	return nil
}

// 根据手机获取会员编号
func (m *MemberQuery) GetMemberIdByPhone(phone string) int {
	id := 0
	m.ExecScalar(`SELECT id FROM mm_member
        INNER JOIN mm_profile ON mm_profile.member_id=mm_member.id
        WHERE mm_profile.phone = ? LIMIT 0,1`, &id, phone)
	return id
}

// 会员推广排名
func (m *MemberQuery) GetMemberInviRank(merchantId int, allTeam bool, levelComp string, level int,
	startTime int64, endTime int64, num int) []*dto.RankMember {
	var list []*dto.RankMember = make([]*dto.RankMember, 0)
	var id int
	var usr, name string
	var inviNum, totalNum, regTime int
	var rank int = 0

	var sortField string = "t.all_num DESC"
	if !allTeam {
		sortField = "t.invi_num DESC"
	}

	var levelCompStr string = fmt.Sprintf("%s%d", levelComp, level)
	//{level_comp}{level_value}

	m.Query(fmt.Sprintf(`SELECT id,usr,name,invi_num,all_num,reg_time FROM ( SELECT m.*,
 (SELECT COUNT(0) FROM mm_relation r INNER JOIN mm_member m1 ON m1.id = r.member_id WHERE
  (m1.level%s) AND r.invi_member_id = m.id
	AND r.reg_merchant_id=rl.reg_merchant_id  AND m1.reg_time BETWEEN
  ? AND ? ) as invi_num,
	((SELECT COUNT(0) FROM mm_relation r INNER JOIN mm_member m1 ON m1.id = r.member_id WHERE
  (m1.level%s) AND r.invi_member_id = m.id
	AND r.reg_merchant_id=rl.reg_merchant_id AND m1.reg_time BETWEEN
  ? AND ? )+
 (SELECT COUNT(0) FROM mm_relation r INNER JOIN mm_member m1
  ON m1.id = r.member_id WHERE (m1.level%s) AND invi_member_id IN
	(SELECT member_id FROM mm_relation r INNER JOIN mm_member m1 ON m1.id = r.member_id WHERE
  (m1.level%s) AND r.invi_member_id =
    m.id AND r.reg_merchant_id=rl.reg_merchant_id AND m1.reg_time BETWEEN
  ? AND ? ))) as all_num
 FROM mm_member m INNER JOIN mm_relation rl ON m.id= rl.member_id
 WHERE rl.reg_merchant_id = ? AND state= ?) t ORDER BY %s,t.reg_time asc
 LIMIT 0,?`, levelCompStr, levelCompStr, levelCompStr, levelCompStr, sortField), func(rows *sql.Rows) {
		for rows.Next() {
			rows.Scan(&id, &usr, &name, &inviNum, &totalNum, &regTime)
			rank++
			list = append(list, &dto.RankMember{
				Id:       id,
				Usr:      usr,
				Name:     name,
				RankNum:  rank,
				InviNum:  inviNum,
				TotalNum: totalNum,
				RegTime:  regTime,
			})
		}
	}, startTime, endTime, startTime, endTime, startTime, endTime, merchantId, 1, num)

	return list
}

// 查询有邀请关系的会员数量
func (m *MemberQuery) GetReferNum(memberId int, layer int) int {
	total := 0
	keyword := fmt.Sprintf("''r%d'':%d", layer, memberId)
	where := "refer_str LIKE '%" + keyword +
		",%' OR refer_str LIKE '%" + keyword + "}'"
	log.Println("SELECT COUNT(0) FROM mm_relation WHERE " + where)
	err := m.ExecScalar("SELECT COUNT(0) FROM mm_relation WHERE "+where, &total)
	if err != nil {
		domain.HandleError(err, "[ Go2o][ Member][ Query]:")
	}
	return total
}

// 获取分页商铺收藏
func (m *MemberQuery) PagedShopFav(memberId int, begin, end int,
	where string) (num int, rows []*dto.PagedShopFav) {
	d := m.Connector
	if len(where) > 0 {
		where = " AND " + where
	}
	d.ExecScalar(fmt.Sprintf(`SELECT COUNT(0) FROM mm_favorite f
	INNER JOIN  mch_shop s ON f.refer_id =s.id
    INNER JOIN mch_online_shop o ON s.id = o.shop_id
    INNER JOIN mch_merchant mch ON mch.id = s.mch_id
    WHERE f.member_id=? AND f.fav_type=? %s`, where), &num,
		memberId, member.FavTypeShop)

	if num > 0 {
		sqlLine := fmt.Sprintf(`SELECT f.id,s.id as shop_id,mch.id as mch_id,
    s.name as shop_name,o.logo,f.update_time FROM mm_favorite f
    INNER JOIN  mch_shop s ON f.refer_id =s.id
    INNER JOIN mch_online_shop o ON s.id = o.shop_id
    INNER JOIN mch_merchant mch ON mch.id = s.mch_id
    WHERE f.member_id=? AND f.fav_type=? %s ORDER BY f.update_time DESC LIMIT ?,?`,
			where)
		d.Query(sqlLine, func(rs *sql.Rows) {
			for rs.Next() {
				e := dto.PagedShopFav{}
				rs.Scan(&e.Id, &e.ShopId, &e.MchId, &e.ShopName,
					&e.Logo, &e.UpdateTime)
				e.Logo = format.GetResUrl(e.Logo)
				rows = append(rows, &e)
			}
		}, memberId, member.FavTypeShop, begin, end-begin)
	} else {
		rows = make([]*dto.PagedShopFav, 0)
	}
	return num, rows
}

// 获取分页商铺收藏
func (m *MemberQuery) PagedGoodsFav(memberId int, begin, end int,
	where string) (num int, rows []*dto.PagedGoodsFav) {
	d := m.Connector
	if len(where) > 0 {
		where = " AND " + where
	}
	d.ExecScalar(fmt.Sprintf(`SELECT COUNT(0) FROM mm_favorite f
    INNER JOIN gs_goods gs ON gs.id = f.refer_id
    INNER JOIN gs_item item ON gs.item_id=item.id
    WHERE f.member_id=? AND f.fav_type=? %s`, where), &num,
		memberId, member.FavTypeGoods)

	if num > 0 {
		sqlLine := fmt.Sprintf(`SELECT f.id,gs.id as goods_id,item.name as goods_name,
            img,sale_price,gs.stock_num,item.update_time
            FROM mm_favorite f INNER JOIN gs_goods gs ON gs.id = f.refer_id
            INNER JOIN gs_item item ON gs.item_id=item.id
            WHERE f.member_id=? AND f.fav_type=? %s ORDER BY f.update_time DESC
            LIMIT ?,?`,
			where)
		d.Query(sqlLine, func(rs *sql.Rows) {
			for rs.Next() {
				e := dto.PagedGoodsFav{}
				rs.Scan(&e.Id, &e.SkuId, &e.GoodsName, &e.Image, &e.SalePrice,
					 &e.StockNum, &e.UpdateTime)
				e.Image = format.GetResUrl(e.Image)
				rows = append(rows, &e)
			}
		}, memberId, member.FavTypeGoods, begin, end-begin)

	} else {
		rows = make([]*dto.PagedGoodsFav, 0)
	}
	return num, rows
}
<|endoftext|>


<commit_before>package pb

import (
	"fmt"
	"strings"
	"sync/atomic"
	"time"
)

var (
	// Default refresh rate - 200ms
	DefaultRefreshRate = time.Millisecond * 200

	BarStart = "["
	BarEnd   = "]"
	Empty    = "_"
	Current  = "="
	CurrentN = ">"
)

// Create new progress bar object
func New(total int) *ProgressBar {
	return &ProgressBar{
		Total:        int64(total),
		RefreshRate:  DefaultRefreshRate,
		ShowPercent:  true,
		ShowCounters: true,
		ShowBar:      true,
	}
}

// Create new object and start
func StartNew(total int) (pb *ProgressBar) {
	pb = New(total)
	pb.Start()
	return
}

type ProgressBar struct {
	Total                              int64
	RefreshRate                        time.Duration
	ShowPercent, ShowCounters, ShowBar bool
	current                            int64
	isFinish                           bool
}

// Start print
func (pb *ProgressBar) Start() {
	go pb.writer()
}

// Increment current value
func (pb *ProgressBar) Increment() int {
	return pb.Add(1)
}

// Set current value
func (pb *ProgressBar) Set(current int) {
	atomic.StoreInt64(&pb.current, int64(current))
}

// Add to current value
func (pb *ProgressBar) Add(add int) int {
	return int(atomic.AddInt64(&pb.current, int64(add)))
}

// End print
func (pb *ProgressBar) Finish() {
	pb.isFinish = true
	pb.write(atomic.LoadInt64(&pb.current))
	fmt.Println()
}

// End print and write string 'str'
func (pb *ProgressBar) FinishPrint(str string) {
	pb.Finish()
	fmt.Println(bold(str))
}

func (pb *ProgressBar) write(current int64) {
	width, _ := terminalWidth()
	var percentBox, countersBox, barBox, end, out string

	// percents
	if pb.ShowPercent {
		percent := float64(current) / (float64(pb.Total) / float64(100))
		percentBox = fmt.Sprintf(" %#.02f %% ", percent)
	}

	// counters
	if pb.ShowCounters {
		countersBox = bold(fmt.Sprintf("%d / %d ", current, pb.Total))
	}

	// bar
	if pb.ShowBar {
		size := width - len(countersBox+BarStart+BarEnd+percentBox)
		if size > 0 {
			curCount := int(float64(current) / (float64(pb.Total) / float64(size)))
			emptCount := size - curCount
			barBox = BarStart
			if emptCount < 0 {
				emptCount = 0
			}
			if curCount > size {
				curCount = size
			}
			if emptCount <= 0 {
				barBox += strings.Repeat(Current, curCount)
			} else if curCount > 0 {
				barBox += strings.Repeat(Current, curCount-1) + CurrentN
			}

			barBox += strings.Repeat(Empty, emptCount) + BarEnd
		}
	}

	// check len
	out = countersBox + barBox + percentBox
	if len(out) < width {
		end = strings.Repeat(" ", width-len(out))
	}

	// bold
	if countersBox != "" {
		countersBox = bold(countersBox)
	}
	if percentBox != "" {
		percentBox = bold(percentBox)
	}
	out = countersBox + barBox + percentBox

	// and print!
	fmt.Print("\r" + out + end)
}

func (pb *ProgressBar) writer() {
	var c, oc int64
	for {
		if pb.isFinish {
			break
		}
		c = atomic.LoadInt64(&pb.current)
		if c != oc {
			pb.write(c)
			oc = c
		}
		time.Sleep(pb.RefreshRate)
	}
}

type window struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}
<commit_msg>Time left support<commit_after>package pb

import (
	"fmt"
	"strings"
	"sync/atomic"
	"time"
)

var (
	// Default refresh rate - 200ms
	DefaultRefreshRate = time.Millisecond * 200

	BarStart = "["
	BarEnd   = "]"
	Empty    = "_"
	Current  = "="
	CurrentN = ">"
)

// Create new progress bar object
func New(total int) *ProgressBar {
	return &ProgressBar{
		Total:        int64(total),
		RefreshRate:  DefaultRefreshRate,
		ShowPercent:  true,
		ShowCounters: true,
		ShowBar:      true,
		ShowTimeLeft: true,
	}
}

// Create new object and start
func StartNew(total int) (pb *ProgressBar) {
	pb = New(total)
	pb.Start()
	return
}

type ProgressBar struct {
	Total                                            int64
	RefreshRate                                      time.Duration
	ShowPercent, ShowCounters, ShowBar, ShowTimeLeft bool
	current                                          int64
	isFinish                                         bool
	startTime                                        time.Time
}

// Start print
func (pb *ProgressBar) Start() {
	pb.startTime = time.Now()
	go pb.writer()
}

// Increment current value
func (pb *ProgressBar) Increment() int {
	return pb.Add(1)
}

// Set current value
func (pb *ProgressBar) Set(current int) {
	atomic.StoreInt64(&pb.current, int64(current))
}

// Add to current value
func (pb *ProgressBar) Add(add int) int {
	return int(atomic.AddInt64(&pb.current, int64(add)))
}

// End print
func (pb *ProgressBar) Finish() {
	pb.isFinish = true
	pb.write(atomic.LoadInt64(&pb.current))
	fmt.Println()
}

// End print and write string 'str'
func (pb *ProgressBar) FinishPrint(str string) {
	pb.Finish()
	fmt.Println(bold(str))
}

func (pb *ProgressBar) write(current int64) {
	width, _ := terminalWidth()
	var percentBox, countersBox, timeLeftBox, barBox, end, out string

	// percents
	if pb.ShowPercent {
		percent := float64(current) / (float64(pb.Total) / float64(100))
		percentBox = fmt.Sprintf(" %#.02f %% ", percent)
	}

	// counters
	if pb.ShowCounters {
		countersBox = bold(fmt.Sprintf("%d / %d ", current, pb.Total))
	}

	// time left
	if pb.ShowTimeLeft && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		perEntry := fromStart / time.Duration(current)
		left := time.Duration(pb.Total-current) * perEntry
		left = (left / time.Second) * time.Second
		if left > 0 {
			timeLeftBox = left.String()
		}
	}

	// bar
	if pb.ShowBar {
		size := width - len(countersBox+BarStart+BarEnd+percentBox+timeLeftBox)
		if size > 0 {
			curCount := int(float64(current) / (float64(pb.Total) / float64(size)))
			emptCount := size - curCount
			barBox = BarStart
			if emptCount < 0 {
				emptCount = 0
			}
			if curCount > size {
				curCount = size
			}
			if emptCount <= 0 {
				barBox += strings.Repeat(Current, curCount)
			} else if curCount > 0 {
				barBox += strings.Repeat(Current, curCount-1) + CurrentN
			}

			barBox += strings.Repeat(Empty, emptCount) + BarEnd
		}
	}

	// check len
	out = countersBox + barBox + percentBox + timeLeftBox
	if len(out) < width {
		end = strings.Repeat(" ", width-len(out))
	}

	// bold
	if countersBox != "" {
		countersBox = bold(countersBox)
	}
	if percentBox != "" {
		percentBox = bold(percentBox)
	}
	out = countersBox + barBox + percentBox + timeLeftBox

	// and print!
	fmt.Print("\r" + out + end)
}

func (pb *ProgressBar) writer() {
	var c, oc int64
	for {
		if pb.isFinish {
			break
		}
		c = atomic.LoadInt64(&pb.current)
		if c != oc {
			pb.write(c)
			oc = c
		}
		time.Sleep(pb.RefreshRate)
	}
}

type window struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}
<|endoftext|>