<commit_before>// This file is based on the github.com/gorilla/schema package

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

package mapping

import (
	"errors"
	"fmt"
	"reflect"
)

// NewDecoder returns a new Decoder.
func NewDecoder() *Decoder {
	return &Decoder{cache: newCache()}
}

// Decoder decodes values from a map[string][]string to a struct.
type Decoder struct {
	cache *fieldCache
}

// RegisterConverter registers a converter function for a custom type.
func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) {
	d.cache.conv[reflect.TypeOf(value).Kind()] = converterFunc
}

// Decode decodes a map[string][]string to a struct.
//
// The first parameter must be a pointer to a struct.
//
// The second parameter is a map, typically url.Values from an HTTP request.
// Keys are "paths" in dotted notation to the struct fields and nested structs.
//
// See the package documentation for a full explanation of the mechanics.
func (d *Decoder) Decode(dst interface{}, src interface{}) error {
	dv := reflect.ValueOf(dst)
	sv := reflect.ValueOf(src)

	// Ensure that the destination is a pointer
	if dv.Kind() != reflect.Ptr {
		return errors.New("schema: destination must be a pointer")
	}
	dv = dv.Elem()
	return d.decode(dv, sv)
}

func (d *Decoder) decode(dv, sv reflect.Value) error {
	if dv.IsValid() && sv.IsValid() {
		// Ensure that the source value has the correct type of parsing
		if sv.Kind() == reflect.Interface {
			sv = reflect.ValueOf(sv.Interface())
		}

		switch dv.Kind() {
		case reflect.Slice, reflect.Array:
			return d.decodeArray(dv, sv)
		case reflect.Struct, reflect.Map:
			return d.decodeObject(dv, sv)
		default:
			return d.decodeLiteral(dv, sv)
		}
	}

	return nil
}

func (d *Decoder) decodeLiteral(dv reflect.Value, sv reflect.Value) error {
	dv = d.indirect(dv)
	dt := dv.Type()

	if dv.Kind() == reflect.Interface {
		dv.Set(reflect.ValueOf(d.decodeLiteralInterface(sv)))
		return nil
	}

	if conv := d.cache.conv[dt.Kind()]; conv != nil {
		if value := conv(sv.Interface()); value.IsValid() {
			dv.Set(value)
		} else {
			return ConversionError{Index: -1}
		}
	} else {
		return fmt.Errorf("schema: converter not found for %v", dt)
	}

	return nil
}

func (d *Decoder) decodeArray(dv reflect.Value, sv reflect.Value) error {
	dv = d.indirect(dv)
	dt := dv.Type()

	if dt.Kind() == reflect.Interface {
		if dv.NumMethod() == 0 {
			// Decoding into nil interface?  Switch to non-reflect code.
			dv.Set(reflect.ValueOf(d.decodeArrayInterface(sv)))

			return nil
		} else {
			return nil
		}
	}

	if dv.Kind() == reflect.Slice {
		dv.Set(reflect.MakeSlice(dt, 0, 0))
	}

	i := 0
	for i < sv.Len() {
		if dv.Kind() == reflect.Slice {
			// Get element of array, growing if necessary.
			if i >= dv.Cap() {
				newcap := dv.Cap() + dv.Cap()/2
				if newcap < 4 {
					newcap = 4
				}
				newdv := reflect.MakeSlice(dv.Type(), dv.Len(), newcap)
				reflect.Copy(newdv, dv)
				dv.Set(newdv)
			}
			if i >= dv.Len() {
				dv.SetLen(i + 1)
			}
		}

		if i < dv.Len() {
			// Decode into element.
			err := d.decode(dv.Index(i), sv.Index(i))
			if err != nil {
				return err
			}
		} else {
			// Ran out of fixed array: skip.
			err := d.decode(reflect.Value{}, sv.Index(i))
			if err != nil {
				return err
			}
		}

		i++
	}
	if i < dv.Len() {
		if dv.Kind() == reflect.Array {
			// Array.  Zero the rest.
			z := reflect.Zero(dv.Type().Elem())
			for ; i < dv.Len(); i++ {
				dv.Index(i).Set(z)
			}
		} else {
			dv.SetLen(i)
		}
	}
	if i == 0 && dv.Kind() == reflect.Slice {
		dv.Set(reflect.MakeSlice(dv.Type(), 0, 0))
	}

	return nil
}

// decode fills a struct field using a parsed path.
func (d *Decoder) decodeObject(dv reflect.Value, sv reflect.Value) error {
	dv = d.indirect(dv)
	dt := dv.Type()

	// Decoding into nil interface?  Switch to non-reflect code.
	if dv.Kind() == reflect.Interface && dv.NumMethod() == 0 {
		dv.Set(reflect.ValueOf(d.decodeObjectInterface(sv)))
		return nil
	}

	if dv.Kind() == reflect.Map {
		// map must have string kind
		if dt.Key().Kind() != reflect.String {
			// d.saveError(&UnmarshalTypeError{"object", dv.Type()})
			return fmt.Errorf("Map key not string...")
		}

		if dv.IsNil() {
			dv.Set(reflect.MakeMap(dt))
		}
	}

	var mapElem reflect.Value

	for _, key := range sv.MapKeys() {
		var subdv reflect.Value
		var subsv reflect.Value = sv.MapIndex(key)

		if dv.Kind() == reflect.Map {
			elemType := dv.Type().Elem()
			if !mapElem.IsValid() {
				mapElem = reflect.New(elemType).Elem()
			} else {
				mapElem.Set(reflect.Zero(elemType))
			}
			subdv = mapElem
		} else {
			var f *field
			fields := d.cache.typeFields(dv.Type())
			for i := range fields {
				ff := &fields[i]
				if ff.name == key.Interface().(string) {
					f = ff
					break
				}
			}
			if f != nil {
				subdv = dv
				for _, i := range f.index {
					if subdv.Kind() == reflect.Ptr {
						if subdv.IsNil() {
							subdv.Set(reflect.New(subdv.Type().Elem()))
						}
						subdv = subdv.Elem()
					}
					subdv = subdv.Field(i)
				}
			}
		}

		err := d.decode(subdv, subsv)
		if err != nil {
			return err
		}

		if dv.Kind() == reflect.Map {
			kv := reflect.ValueOf(key.Interface().(string))
			dv.SetMapIndex(kv, subdv)
		}
	}

	return nil
}

// The xxxInterface routines build up a value to be stored
// in an empty interface.  They are not strictly necessary,
// but they avoid the weight of reflection in this common case.

// valueInterface is like value but returns interface{}
func (d *Decoder) decodeInterface(sv reflect.Value) interface{} {
	switch sv.Kind() {
	case reflect.Array, reflect.Slice:
		return d.decodeArrayInterface(sv)
	case reflect.Struct, reflect.Map:
		return d.decodeObjectInterface(sv)
	default:
		return d.decodeLiteralInterface(sv)
	}
}

// arrayInterface is like array but returns []interface{}.
func (d *Decoder) decodeArrayInterface(sv reflect.Value) []interface{} {
	var arr = make([]interface{}, 0)
	for _, v := range sv.Interface().([]interface{}) {
		arr = append(arr, d.decodeInterface(reflect.ValueOf(v)))
	}
	return arr
}

// objectInterface is like object but returns map[string]interface{}.
func (d *Decoder) decodeObjectInterface(sv reflect.Value) map[string]interface{} {
	m := make(map[string]interface{})
	for k, v := range sv.Interface().(map[string]interface{}) {
		m[k] = d.decodeInterface(reflect.ValueOf(v))
	}
	return m
}

// literalInterface is like literal but returns an interface value.
func (d *Decoder) decodeLiteralInterface(sv reflect.Value) interface{} {
	return sv.Interface()
}

// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
func (d *Decoder) indirect(v reflect.Value) reflect.Value {
	// If v is a named type and is addressable,
	// start with its address, so that if the type has pointer methods,
	// we find them.
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		v = v.Addr()
	}
	for {
		// Load value from interface, but only if the result will be
		// usefully addressable.
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && e.Elem().Kind() == reflect.Ptr {
				v = e
				continue
			}
		}

		if v.Kind() != reflect.Ptr {
			break
		}

		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		v = v.Elem()
	}
	return v
}

// Errors ---------------------------------------------------------------------

// ConversionError stores information about a failed conversion.
type ConversionError struct {
	Key   string // key from the source map.
	Index int    // index for multi-value fields; -1 for single-value fields.
}

func (e ConversionError) Error() string {
	if e.Index < 0 {
		return fmt.Sprintf("schema: error converting value for %q", e.Key)
	}
	return fmt.Sprintf("schema: error converting value for index %d of %q",
		e.Index, e.Key)
}

// MultiError stores multiple decoding errors.
//
// Borrowed from the App Engine SDK.
type MultiError map[string]error

func (e MultiError) Error() string {
	s := ""
	for _, err := range e {
		s = err.Error()
		break
	}
	switch len(e) {
	case 0:
		return "(0 errors)"
	case 1:
		return s
	case 2:
		return s + " (and 1 other error)"
	}
	return fmt.Sprintf("%s (and %d other errors)", s, len(e)-1)
}
<commit_msg>Updated mapper to ensure that maps are of type map[string]interface{}. This is because rethink always returns keys that are strings<commit_after>// This file is based on the github.com/gorilla/schema package

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

package mapping

import (
	"errors"
	"fmt"
	"reflect"
)

// NewDecoder returns a new Decoder.
func NewDecoder() *Decoder {
	return &Decoder{cache: newCache()}
}

// Decoder decodes values from a map[string][]string to a struct.
type Decoder struct {
	cache *fieldCache
}

// RegisterConverter registers a converter function for a custom type.
func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) {
	d.cache.conv[reflect.TypeOf(value).Kind()] = converterFunc
}

// Decode decodes a map[string][]string to a struct.
//
// The first parameter must be a pointer to a struct.
//
// The second parameter is a map, typically url.Values from an HTTP request.
// Keys are "paths" in dotted notation to the struct fields and nested structs.
//
// See the package documentation for a full explanation of the mechanics.
func (d *Decoder) Decode(dst interface{}, src interface{}) error {
	dv := reflect.ValueOf(dst)
	sv := reflect.ValueOf(src)

	// Ensure that the destination is a pointer
	if dv.Kind() != reflect.Ptr {
		return errors.New("schema: destination must be a pointer")
	}
	dv = dv.Elem()

	return d.decode(dv, sv)
}

func (d *Decoder) decode(dv, sv reflect.Value) error {
	if dv.IsValid() && sv.IsValid() {
		// Ensure that the source value has the correct type of parsing
		if sv.Kind() == reflect.Interface {
			sv = reflect.ValueOf(sv.Interface())
		}

		switch sv.Kind() {
		case reflect.Slice, reflect.Array:
			return d.decodeArray(dv, sv)
		case reflect.Struct, reflect.Map:
			return d.decodeObject(dv, sv)
		default:
			return d.decodeLiteral(dv, sv)
		}
	}

	return nil
}

func (d *Decoder) decodeLiteral(dv reflect.Value, sv reflect.Value) error {
	dv = d.indirect(dv)
	dt := dv.Type()

	if dv.Kind() == reflect.Interface {
		dv.Set(reflect.ValueOf(d.decodeLiteralInterface(sv)))
		return nil
	}

	if conv := d.cache.conv[dt.Kind()]; conv != nil {
		if value := conv(sv.Interface()); value.IsValid() {
			dv.Set(value)
		} else {
			return ConversionError{Index: -1}
		}
	} else {
		return fmt.Errorf("schema: converter not found for %v", dt)
	}

	return nil
}

func (d *Decoder) decodeArray(dv reflect.Value, sv reflect.Value) error {
	dv = d.indirect(dv)
	dt := dv.Type()

	if dt.Kind() == reflect.Interface {
		if dv.NumMethod() == 0 {
			// Decoding into nil interface?  Switch to non-reflect code.
			dv.Set(reflect.ValueOf(d.decodeArrayInterface(sv)))

			return nil
		} else {
			return nil
		}
	}

	if dv.Kind() == reflect.Slice {
		dv.Set(reflect.MakeSlice(dt, 0, 0))
	}

	i := 0
	for i < sv.Len() {
		if dv.Kind() == reflect.Slice {
			// Get element of array, growing if necessary.
			if i >= dv.Cap() {
				newcap := dv.Cap() + dv.Cap()/2
				if newcap < 4 {
					newcap = 4
				}
				newdv := reflect.MakeSlice(dv.Type(), dv.Len(), newcap)
				reflect.Copy(newdv, dv)
				dv.Set(newdv)
			}
			if i >= dv.Len() {
				dv.SetLen(i + 1)
			}
		}

		if i < dv.Len() {
			// Decode into element.
			err := d.decode(dv.Index(i), sv.Index(i))
			if err != nil {
				return err
			}
		} else {
			// Ran out of fixed array: skip.
			err := d.decode(reflect.Value{}, sv.Index(i))
			if err != nil {
				return err
			}
		}

		i++
	}
	if i < dv.Len() {
		if dv.Kind() == reflect.Array {
			// Array.  Zero the rest.
			z := reflect.Zero(dv.Type().Elem())
			for ; i < dv.Len(); i++ {
				dv.Index(i).Set(z)
			}
		} else {
			dv.SetLen(i)
		}
	}
	if i == 0 && dv.Kind() == reflect.Slice {
		dv.Set(reflect.MakeSlice(dv.Type(), 0, 0))
	}

	return nil
}

// decode fills a struct field using a parsed path.
func (d *Decoder) decodeObject(dv reflect.Value, sv reflect.Value) error {
	dv = d.indirect(dv)
	dt := dv.Type()

	// Decoding into nil interface?  Switch to non-reflect code.
	if dv.Kind() == reflect.Interface && dv.NumMethod() == 0 {
		dv.Set(reflect.ValueOf(d.decodeObjectInterface(sv)))
		return nil
	}

	if dv.Kind() == reflect.Map {
		// map must have string kind
		if dt.Key().Kind() != reflect.String {
			// d.saveError(&UnmarshalTypeError{"object", dv.Type()})
			return fmt.Errorf("Map key not string...")
		}

		if dv.IsNil() {
			dv.Set(reflect.MakeMap(dt))
		}
	}

	var mapElem reflect.Value

	for _, key := range sv.MapKeys() {
		var subdv reflect.Value
		var subsv reflect.Value = sv.MapIndex(key)

		if dv.Kind() == reflect.Map {
			elemType := dv.Type().Elem()
			if !mapElem.IsValid() {
				mapElem = reflect.New(elemType).Elem()
			} else {
				mapElem.Set(reflect.Zero(elemType))
			}
			subdv = mapElem
		} else {
			var f *field
			fields := d.cache.typeFields(dv.Type())
			for i := range fields {
				ff := &fields[i]
				if ff.name == key.Interface().(string) {
					f = ff
					break
				}
			}
			if f != nil {
				subdv = dv
				for _, i := range f.index {
					if subdv.Kind() == reflect.Ptr {
						if subdv.IsNil() {
							subdv.Set(reflect.New(subdv.Type().Elem()))
						}
						subdv = subdv.Elem()
					}
					subdv = subdv.Field(i)
				}
			}
		}

		err := d.decode(subdv, subsv)
		if err != nil {
			return err
		}

		if dv.Kind() == reflect.Map {
			kv := reflect.ValueOf(key.Interface().(string))
			dv.SetMapIndex(kv, subdv)
		}
	}

	return nil
}

// The xxxInterface routines build up a value to be stored
// in an empty interface.  They are not strictly necessary,
// but they avoid the weight of reflection in this common case.

// valueInterface is like value but returns interface{}
func (d *Decoder) decodeInterface(sv reflect.Value) interface{} {
	switch sv.Kind() {
	case reflect.Array, reflect.Slice:
		return d.decodeArrayInterface(sv)
	case reflect.Struct, reflect.Map:
		return d.decodeObjectInterface(sv)
	default:
		return d.decodeLiteralInterface(sv)
	}
}

// arrayInterface is like array but returns []interface{}.
func (d *Decoder) decodeArrayInterface(sv reflect.Value) []interface{} {
	var arr = make([]interface{}, 0)
	for _, v := range sv.Interface().([]interface{}) {
		arr = append(arr, d.decodeInterface(reflect.ValueOf(v)))
	}
	return arr
}

// objectInterface is like object but returns map[string]interface{}.
func (d *Decoder) decodeObjectInterface(sv reflect.Value) map[string]interface{} {
	m := make(map[string]interface{})
	for k, v := range sv.Interface().(map[interface{}]interface{}) {
		// Ensure that key is of type string
		if key, ok := k.(string); ok {
			m[key] = d.decodeInterface(reflect.ValueOf(v))
		}
	}
	return m
}

// literalInterface is like literal but returns an interface value.
func (d *Decoder) decodeLiteralInterface(sv reflect.Value) interface{} {
	return sv.Interface()
}

// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
func (d *Decoder) indirect(v reflect.Value) reflect.Value {
	// If v is a named type and is addressable,
	// start with its address, so that if the type has pointer methods,
	// we find them.
	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
		v = v.Addr()
	}
	for {
		// Load value from interface, but only if the result will be
		// usefully addressable.
		if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && e.Elem().Kind() == reflect.Ptr {
				v = e
				continue
			}
		}

		if v.Kind() != reflect.Ptr {
			break
		}

		if v.IsNil() {
			v.Set(reflect.New(v.Type().Elem()))
		}
		v = v.Elem()
	}
	return v
}

// Errors ---------------------------------------------------------------------

// ConversionError stores information about a failed conversion.
type ConversionError struct {
	Key   string // key from the source map.
	Index int    // index for multi-value fields; -1 for single-value fields.
}

func (e ConversionError) Error() string {
	if e.Index < 0 {
		return fmt.Sprintf("schema: error converting value for %q", e.Key)
	}
	return fmt.Sprintf("schema: error converting value for index %d of %q",
		e.Index, e.Key)
}

// MultiError stores multiple decoding errors.
//
// Borrowed from the App Engine SDK.
type MultiError map[string]error

func (e MultiError) Error() string {
	s := ""
	for _, err := range e {
		s = err.Error()
		break
	}
	switch len(e) {
	case 0:
		return "(0 errors)"
	case 1:
		return s
	case 2:
		return s + " (and 1 other error)"
	}
	return fmt.Sprintf("%s (and %d other errors)", s, len(e)-1)
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"log"
	"net"
	"os"
	"strconv"
	"time"
)
import (
	"runtime/pprof"
	"runtime"
	"flag"
)

func main() {
	cpuprofile := flag.String("cpuprofile", "", "write cpu profile to file")
	commandtype := flag.String("type", "", "server or client")
	service := flag.String("service", "", "like :8080")
	times := flag.Int("times", 1, "client exec times")
	flag.Parse()
	runtime.SetBlockProfileRate(1)
	log.Println(*cpuprofile)
	if *cpuprofile != "" {
		log.Println("cpuprofiling")
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}
	if *commandtype == "client" {
		client(*service, *times)
	} else if *commandtype == "server" {
		server(*service, *times)
	} else {
		log.Fatal("not exists type: " + *commandtype)
		log.Fatal(flag.Usage)
	}
}

func dieIfError(err error) {
	if err != nil {
		log.Fatal("Fatal error: %s", err.Error())
	}
}

func client(service string, times int) {
	tcpAddr, err := net.ResolveTCPAddr("tcp", service)
	dieIfError(err)
	for i := 0; i < times; i++ {
		conn, err := net.DialTCP("tcp", nil, tcpAddr)
		dieIfError(err)
		_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))
		dieIfError(err)
		result, err := ioutil.ReadAll(conn)
		dieIfError(err)
		log.Println(string(result))
	}
}

func server(service string, times int) {
	tcpAddr, err := net.ResolveTCPAddr("tcp", service)
	dieIfError(err)
	listener, err := net.ListenTCP("tcp", tcpAddr)
	dieIfError(err)
	count := 0
	for {
		conn, err := listener.Accept()
		if err != nil {
			continue
		}
		count += 1
		responce(conn, count)
		if count == times {
			return
		}
	}

}

func responce(conn net.Conn, count int) {
	defer conn.Close()
	now := time.Now().String()
	log.Println(strconv.Itoa(count) + " Access come !")
	conn.Write([]byte(now))
}
<commit_msg>省略しない<commit_after>package main

import (
	"io/ioutil"
	"log"
	"net"
	"os"
	"strconv"
	"time"
)
import (
	"runtime/pprof"
	"runtime"
	"flag"
)

func main() {
	cpuprofile := flag.String("cpuprofile", "", "write cpu profile to file")
	commandtype := flag.String("type", "", "server or client")
	service := flag.String("service", "", "like :8080")
	times := flag.Int("times", 1, "client exec times")
	flag.Parse()
	runtime.SetBlockProfileRate(1)
	log.Println(*cpuprofile)
	if *cpuprofile != "" {
		log.Println("cpuprofiling")
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}
	if *commandtype == "client" {
		client(*service, *times)
	} else if *commandtype == "server" {
		server(*service, *times)
	} else {
		log.Fatal("not exists type: " + *commandtype)
		log.Fatal(flag.Usage)
	}
}

func dieIfError(err error) {
}

func client(service string, times int) {
	tcpAddr, err := net.ResolveTCPAddr("tcp", service)
	if err != nil {
		log.Fatal("Fatal error: %s", err.Error())
	}
	for i := 0; i < times; i++ {
		conn, err := net.DialTCP("tcp", nil, tcpAddr)
		if err != nil {
			log.Fatal("Fatal error: %s", err.Error())
		}
		_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))
		if err != nil {
			log.Fatal("Fatal error: %s", err.Error())
		}
		result, err := ioutil.ReadAll(conn)
		if err != nil {
			log.Fatal("Fatal error: %s", err.Error())
		}
		log.Println(string(result))
	}
}

func server(service string, times int) {
	tcpAddr, err := net.ResolveTCPAddr("tcp", service)
	if err != nil {
		log.Fatal("Fatal error: %s", err.Error())
	}
	listener, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		log.Fatal("Fatal error: %s", err.Error())
	}
	count := 0
	for {
		conn, err := listener.Accept()
		if err != nil {
			continue
		}
		count += 1
		responce(conn, count)
		if count == times {
			return
		}
	}

}

func responce(conn net.Conn, count int) {
	defer conn.Close()
	now := time.Now().String()
	log.Println(strconv.Itoa(count) + " Access come !")
	conn.Write([]byte(now))
}
<|endoftext|>


<commit_before>/*

   Copyright since 2017 Wenhui Shen <www.webx.top>

   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 pagination

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html/template"
	"math"
	"strconv"
	"strings"

	"github.com/webx-top/echo"
	"github.com/webx-top/echo/engine"
)

const (
	// ModePageNumber 页码模式
	ModePageNumber = iota + 1
	// ModePosition 偏移值模式
	ModePosition
)

var (
	// DefaultPageVarsMap tagName=>urlVar
	DefaultPageVarsMap = map[string]string{
		`rows`: `rows`,
		`page`: `page`,
		`size`: `size`,
	}
	// DefaultPositionVarsMap tagName=>urlVar
	DefaultPositionVarsMap = map[string]string{
		`curr`: `offset`,
		`prev`: `prev`,
		`next`: `next`,
	}
)

// New 创建分页实例
func New(ctx echo.Context) *Pagination {
	return &Pagination{context: ctx, pages: -1, data: echo.H{}, mode: ModePageNumber}
}

// Pagination 分页
type Pagination struct {
	context   echo.Context
	tmpl      string
	urlLayout string
	data      echo.H
	mode      int

	// 按基准位置分页
	position     string
	prevPosition string
	nextPosition string

	// 按页码分页
	page  int
	rows  int //总行数
	size  int //每页数据行数
	num   int //页码链接数量
	pages int //总页数

}

// SetAll 设置按页码分页模式所需的所有参数
// tmpl 模板
// rows 总行数
// pnl[0] 当前页码
// pnl[1] 分页链接数量
// pnl[2] 每页数量
func (p *Pagination) SetAll(tmpl string, rows int, pnl ...int) *Pagination {
	switch len(pnl) {
	case 3:
		p.size = pnl[2]
		fallthrough
	case 2:
		p.num = pnl[1]
		fallthrough
	case 1:
		p.page = pnl[0]
	}
	p.rows = rows
	p.tmpl = tmpl
	p.pages = -1
	return p
}

// SetPosition 设置按偏移值分页模式所需的所有参数
// prev 上一页偏移值
// next 下一页偏移值
// curr 当前页偏移值
func (p *Pagination) SetPosition(prev string, next string, curr string) *Pagination {
	p.prevPosition = prev
	p.nextPosition = next
	p.position = curr
	p.mode = ModePosition
	return p
}

// Set 设置附加数据
func (p *Pagination) Set(key string, data interface{}) *Pagination {
	p.data[key] = data
	return p
}

// Sets 设置多个附加数据(参数按照key,value,key1,value1的格式)
func (p *Pagination) Sets(args ...interface{}) *Pagination {
	var key string
	for i, j := 0, len(args); i < j; i++ {
		if i%2 == 0 {
			key = fmt.Sprint(args[i])
			continue
		}
		p.data[key] = args[i]
	}
	return p
}

// Get 获取某个附加数据
func (p *Pagination) Get(key string) interface{} {
	if v, y := p.data[key]; y {
		return v
	}
	return nil
}

// Data 获取整个附加数据
func (p *Pagination) Data() echo.H {
	return p.data
}

// Position 当前偏移值
func (p *Pagination) Position() string {
	return p.position
}

// PrevPosition 上一页偏移值
func (p *Pagination) PrevPosition() string {
	return p.prevPosition
}

// NextPosition 下一页偏移值
func (p *Pagination) NextPosition() string {
	return p.nextPosition
}

// HasNext 是否有下一页
func (p *Pagination) HasNext() bool {
	if p.mode == ModePageNumber {
		return p.Page() < p.Pages()
	}
	return len(p.NextPosition()) > 0 && p.NextPosition() != `0` && p.NextPosition() != p.Position()
}

// HasPrev 是否有上一页
func (p *Pagination) HasPrev() bool {
	if p.mode == ModePageNumber {
		return p.Page() > 1
	}
	return p.PrevPosition() != `0` && p.PrevPosition() != p.Position()

}

func (p *Pagination) SetPage(page int) *Pagination {
	p.page = page
	return p
}

func (p *Pagination) Page() int {
	return p.page
}

func (p *Pagination) PrevPage() int {
	if p.page < 2 {
		return 1
	}
	return p.page - 1
}

func (p *Pagination) NextPage() int {
	n := p.page + 1
	if n <= p.pages {
		return n
	}
	return p.pages
}

func (p *Pagination) SetRows(rows int) *Pagination {
	p.pages = -1
	p.rows = rows
	return p
}

func (p *Pagination) Rows() int {
	return p.rows
}

func (p *Pagination) SetLimit(limit int) *Pagination {
	p.pages = -1
	p.size = limit
	return p
}

// SetSize SetLimit方法的别名
func (p *Pagination) SetSize(size int) *Pagination {
	return p.SetLimit(size)
}

func (p *Pagination) Limit() int {
	return p.size
}

// Size Limit方法的别名
func (p *Pagination) Size() int {
	return p.Limit()
}

func (p *Pagination) SetNum(num int) *Pagination {
	p.num = num
	return p
}

func (p *Pagination) Num() int {
	return p.num
}

func (p *Pagination) SetTmpl(tmpl string) *Pagination {
	p.tmpl = tmpl
	return p
}

func (p *Pagination) Tmpl() string {
	return p.tmpl
}

func (p *Pagination) Pages() int {
	if p.pages == -1 {
		p.pages = int(math.Ceil(float64(p.rows) / float64(p.size)))
	}
	return p.pages
}

func (p *Pagination) URL(curr interface{}) (s string) {
	if p.mode == ModePageNumber {
		size := strconv.Itoa(p.size)
		s = strings.Replace(p.urlLayout, `{page}`, fmt.Sprint(curr), -1)
		s = strings.Replace(s, `{rows}`, strconv.Itoa(p.rows), -1)
		s = strings.Replace(s, `{size}`, size, -1)
		s = strings.Replace(s, `{limit}`, size, -1)
		s = strings.Replace(s, `{pages}`, strconv.Itoa(p.pages), -1)
	} else {
		s = strings.Replace(p.urlLayout, `{curr}`, fmt.Sprint(curr), -1)
		s = strings.Replace(s, `{prev}`, p.prevPosition, -1)
		s = strings.Replace(s, `{next}`, p.nextPosition, -1)
	}
	return s
}

func (p *Pagination) SetURL(s interface{}, delKeys ...string) *Pagination {
	switch v := s.(type) {
	case string:
		p.urlLayout = v
	case map[string]string:
		p.urlLayout = p.RebuildURL(v, delKeys...)
	case nil:
		if p.mode == ModePageNumber {
			p.urlLayout = p.RebuildURL(DefaultPageVarsMap, delKeys...)
		} else {
			p.urlLayout = p.RebuildURL(DefaultPositionVarsMap, delKeys...)
		}
	default:
		panic(`Unsupported type: ` + fmt.Sprintf(`%T`, s))
	}
	return p
}

func (p *Pagination) RebuildQueryString(delKeys ...string) string {
	query := p.context.Request().URL().Query()
	for _, key := range delKeys {
		query.Del(key)
	}
	return query.Encode()
}

func (p *Pagination) RebuildURL(pageVars map[string]string, delKeys ...string) string {
	var (
		pq string
		jn string
	)
	for name, urlVar := range pageVars {
		delKeys = append(delKeys, urlVar)
		pq += jn + urlVar + `={` + name + `}`
		jn = `&`
	}
	q := p.RebuildQueryString(delKeys...)
	if len(q) > 0 {
		q += `&`
	}
	url := p.context.Request().URL().Path() + `?` + q + pq
	return url
}

func (p *Pagination) List(num ...int) []int {
	if len(num) > 0 {
		p.num = num[0]
	}
	pages := p.Pages()
	var (
		pList []int
		start int
		count int
	)
	remainPages := pages - p.page
	if remainPages < p.num {
		start = pages - p.num + 1
	} else {
		start = p.Page() - (p.num / 2)
	}
	if start < 1 {
		start = 1
	}
	for page := start; page <= pages; page++ {
		count++
		if count > p.num {
			break
		}
		pList = append(pList, page)
	}
	return pList
}

func (p *Pagination) setDefault() *Pagination {
	if p.mode == ModePageNumber {
		if p.page < 1 {
			p.page = 1
		}
		if p.size < 1 {
			p.size = 50
		}
		if p.num < 1 {
			p.num = 10
		}
	}
	return p
}

func (p *Pagination) Render(settings ...string) interface{} {
	p.setDefault()
	switch len(settings) {
	case 1:
		p.tmpl = settings[0]
	}
	if len(p.tmpl) == 0 {
		p.tmpl = `pagination`
	}
	b, e := p.context.Fetch(p.tmpl, p)
	if e != nil {
		return e
	}
	return template.HTML(string(b))
}

// MarshalJSON allows type Pagination to be used with json.Marshal
func (p *Pagination) MarshalJSON() ([]byte, error) {
	b, e := json.Marshal(p.data)
	var s string
	if e != nil {
		s = fmt.Sprintf(`%q`, e.Error())
	} else {
		s = engine.Bytes2str(b)
	}
	if p.mode == ModePageNumber {
		p.setDefault()
		s = fmt.Sprintf(`{"page":%d,"rows":%d,"size":%d,"limit":%d,"pages":%d,"urlLayout":%q,"data":%s}`, p.Page(), p.Rows(), p.Size(), p.Limit(), p.Pages(), p.urlLayout, s)
	} else {
		s = fmt.Sprintf(`{"curr":%q,"prev":%q,"next":%q,"urlLayout":%q,"data":%s}`, p.Position(), p.PrevPosition(), p.NextPosition(), p.urlLayout, s)
	}
	return engine.Str2bytes(s), nil
}

func (p *Pagination) SetOptions(m echo.H) *Pagination {
	if _, y := m[`page`]; y {
		p.mode = ModePageNumber
		p.page = m.Int(`page`)
		p.rows = m.Int(`rows`)
		p.size = m.Int(`size`)
		if p.size <= 0 && m.Has(`limit`) {
			p.size = m.Int(`limit`)
		}
		p.pages = m.Int(`pages`)
	} else {
		p.mode = ModePosition
		p.position = m.String(`curr`)
		p.prevPosition = m.String(`prev`)
		p.nextPosition = m.String(`next`)
	}
	p.urlLayout = m.String(`urlLayout`)
	p.data = m.Store(`data`)
	return p
}

func (p *Pagination) Options() echo.H {
	m := echo.H{}
	if p.mode == ModePageNumber {
		m.Set(`page`, p.page)
		m.Set(`rows`, p.rows)
		m.Set(`size`, p.size)
		m.Set(`limit`, p.size)
		m.Set(`pages`, p.pages)
	} else {
		m.Set(`curr`, p.position)
		m.Set(`prev`, p.prevPosition)
		m.Set(`next`, p.nextPosition)
	}
	m.Set(`urlLayout`, p.urlLayout)
	m.Set(`data`, p.data)
	return m
}

// MarshalXML allows type Pagination to be used with xml.Marshal
func (p *Pagination) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	start.Name.Local = `Pagination`
	if err := e.EncodeToken(start); err != nil {
		return err
	}
	if p.mode == ModePageNumber {
		p.setDefault()
		if err := xmlEncode(e, `page`, p.Page()); err != nil {
			return err
		}
		if err := xmlEncode(e, `rows`, p.Rows()); err != nil {
			return err
		}
		if err := xmlEncode(e, `limit`, p.Limit()); err != nil {
			return err
		}
		if err := xmlEncode(e, `size`, p.Size()); err != nil {
			return err
		}
		if err := xmlEncode(e, `pages`, p.Pages()); err != nil {
			return err
		}
	} else {
		if err := xmlEncode(e, `curr`, p.Position()); err != nil {
			return err
		}
		if err := xmlEncode(e, `prev`, p.PrevPosition()); err != nil {
			return err
		}
		if err := xmlEncode(e, `next`, p.NextPosition()); err != nil {
			return err
		}
	}
	if err := xmlEncode(e, `urlLayout`, p.urlLayout); err != nil {
		return err
	}
	if err := xmlEncode(e, `data`, p.data); err != nil {
		return err
	}
	return e.EncodeToken(xml.EndElement{Name: start.Name})
}

func xmlEncode(e *xml.Encoder, key string, value interface{}) error {
	elem := xml.StartElement{
		Name: xml.Name{Space: ``, Local: key},
		Attr: []xml.Attr{},
	}
	return e.EncodeElement(value, elem)
}
<commit_msg>Added Pagination#Offset()<commit_after>/*

   Copyright since 2017 Wenhui Shen <www.webx.top>

   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 pagination

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html/template"
	"math"
	"strconv"
	"strings"

	"github.com/webx-top/echo"
	"github.com/webx-top/echo/engine"
)

const (
	// ModePageNumber 页码模式
	ModePageNumber = iota + 1
	// ModePosition 偏移值模式
	ModePosition
)

var (
	// DefaultPageVarsMap tagName=>urlVar
	DefaultPageVarsMap = map[string]string{
		`rows`: `rows`,
		`page`: `page`,
		`size`: `size`,
	}
	// DefaultPositionVarsMap tagName=>urlVar
	DefaultPositionVarsMap = map[string]string{
		`curr`: `offset`,
		`prev`: `prev`,
		`next`: `next`,
	}
)

// New 创建分页实例
func New(ctx echo.Context) *Pagination {
	return &Pagination{context: ctx, pages: -1, data: echo.H{}, mode: ModePageNumber}
}

// Pagination 分页
type Pagination struct {
	context   echo.Context
	tmpl      string
	urlLayout string
	data      echo.H
	mode      int

	// 按基准位置分页
	position     string
	prevPosition string
	nextPosition string

	// 按页码分页
	page  int
	rows  int //总行数
	size  int //每页数据行数
	num   int //页码链接数量
	pages int //总页数

}

// SetAll 设置按页码分页模式所需的所有参数
// tmpl 模板
// rows 总行数
// pnl[0] 当前页码
// pnl[1] 分页链接数量
// pnl[2] 每页数量
func (p *Pagination) SetAll(tmpl string, rows int, pnl ...int) *Pagination {
	switch len(pnl) {
	case 3:
		p.size = pnl[2]
		fallthrough
	case 2:
		p.num = pnl[1]
		fallthrough
	case 1:
		p.page = pnl[0]
	}
	p.rows = rows
	p.tmpl = tmpl
	p.pages = -1
	return p
}

// SetPosition 设置按偏移值分页模式所需的所有参数
// prev 上一页偏移值
// next 下一页偏移值
// curr 当前页偏移值
func (p *Pagination) SetPosition(prev string, next string, curr string) *Pagination {
	p.prevPosition = prev
	p.nextPosition = next
	p.position = curr
	p.mode = ModePosition
	return p
}

// Set 设置附加数据
func (p *Pagination) Set(key string, data interface{}) *Pagination {
	p.data[key] = data
	return p
}

// Sets 设置多个附加数据(参数按照key,value,key1,value1的格式)
func (p *Pagination) Sets(args ...interface{}) *Pagination {
	var key string
	for i, j := 0, len(args); i < j; i++ {
		if i%2 == 0 {
			key = fmt.Sprint(args[i])
			continue
		}
		p.data[key] = args[i]
	}
	return p
}

// Get 获取某个附加数据
func (p *Pagination) Get(key string) interface{} {
	if v, y := p.data[key]; y {
		return v
	}
	return nil
}

// Data 获取整个附加数据
func (p *Pagination) Data() echo.H {
	return p.data
}

// Position 当前偏移值
func (p *Pagination) Position() string {
	return p.position
}

// PrevPosition 上一页偏移值
func (p *Pagination) PrevPosition() string {
	return p.prevPosition
}

// NextPosition 下一页偏移值
func (p *Pagination) NextPosition() string {
	return p.nextPosition
}

// HasNext 是否有下一页
func (p *Pagination) HasNext() bool {
	if p.mode == ModePageNumber {
		return p.Page() < p.Pages()
	}
	return len(p.NextPosition()) > 0 && p.NextPosition() != `0` && p.NextPosition() != p.Position()
}

// HasPrev 是否有上一页
func (p *Pagination) HasPrev() bool {
	if p.mode == ModePageNumber {
		return p.Page() > 1
	}
	return p.PrevPosition() != `0` && p.PrevPosition() != p.Position()

}

func (p *Pagination) SetPage(page int) *Pagination {
	p.page = page
	return p
}

func (p *Pagination) Page() int {
	return p.page
}

func (p *Pagination) PrevPage() int {
	if p.page < 2 {
		return 1
	}
	return p.page - 1
}

func (p *Pagination) NextPage() int {
	n := p.page + 1
	if n <= p.pages {
		return n
	}
	return p.pages
}

func (p *Pagination) SetRows(rows int) *Pagination {
	p.pages = -1
	p.rows = rows
	return p
}

func (p *Pagination) Rows() int {
	return p.rows
}

func (p *Pagination) SetLimit(limit int) *Pagination {
	p.pages = -1
	p.size = limit
	return p
}

// SetSize SetLimit方法的别名
func (p *Pagination) SetSize(size int) *Pagination {
	return p.SetLimit(size)
}

func (p *Pagination) Limit() int {
	return p.size
}

// Size Limit方法的别名
func (p *Pagination) Size() int {
	return p.Limit()
}

func (p *Pagination) SetNum(num int) *Pagination {
	p.num = num
	return p
}

func (p *Pagination) Num() int {
	return p.num
}

func (p *Pagination) SetTmpl(tmpl string) *Pagination {
	p.tmpl = tmpl
	return p
}

func (p *Pagination) Tmpl() string {
	return p.tmpl
}

func (p *Pagination) Pages() int {
	if p.pages == -1 {
		p.pages = int(math.Ceil(float64(p.rows) / float64(p.size)))
	}
	return p.pages
}

func (p *Pagination) Offset() int {
	if p.page < 1 {
		return 0
	}
	return (p.page - 1) * p.size
}

func (p *Pagination) URL(curr interface{}) (s string) {
	if p.mode == ModePageNumber {
		size := strconv.Itoa(p.size)
		s = strings.Replace(p.urlLayout, `{page}`, fmt.Sprint(curr), -1)
		s = strings.Replace(s, `{rows}`, strconv.Itoa(p.rows), -1)
		s = strings.Replace(s, `{size}`, size, -1)
		s = strings.Replace(s, `{limit}`, size, -1)
		s = strings.Replace(s, `{pages}`, strconv.Itoa(p.pages), -1)
	} else {
		s = strings.Replace(p.urlLayout, `{curr}`, fmt.Sprint(curr), -1)
		s = strings.Replace(s, `{prev}`, p.prevPosition, -1)
		s = strings.Replace(s, `{next}`, p.nextPosition, -1)
	}
	return s
}

func (p *Pagination) SetURL(s interface{}, delKeys ...string) *Pagination {
	switch v := s.(type) {
	case string:
		p.urlLayout = v
	case map[string]string:
		p.urlLayout = p.RebuildURL(v, delKeys...)
	case nil:
		if p.mode == ModePageNumber {
			p.urlLayout = p.RebuildURL(DefaultPageVarsMap, delKeys...)
		} else {
			p.urlLayout = p.RebuildURL(DefaultPositionVarsMap, delKeys...)
		}
	default:
		panic(`Unsupported type: ` + fmt.Sprintf(`%T`, s))
	}
	return p
}

func (p *Pagination) RebuildQueryString(delKeys ...string) string {
	query := p.context.Request().URL().Query()
	for _, key := range delKeys {
		query.Del(key)
	}
	return query.Encode()
}

func (p *Pagination) RebuildURL(pageVars map[string]string, delKeys ...string) string {
	var (
		pq string
		jn string
	)
	for name, urlVar := range pageVars {
		delKeys = append(delKeys, urlVar)
		pq += jn + urlVar + `={` + name + `}`
		jn = `&`
	}
	q := p.RebuildQueryString(delKeys...)
	if len(q) > 0 {
		q += `&`
	}
	url := p.context.Request().URL().Path() + `?` + q + pq
	return url
}

func (p *Pagination) List(num ...int) []int {
	if len(num) > 0 {
		p.num = num[0]
	}
	pages := p.Pages()
	var (
		pList []int
		start int
		count int
	)
	remainPages := pages - p.page
	if remainPages < p.num {
		start = pages - p.num + 1
	} else {
		start = p.Page() - (p.num / 2)
	}
	if start < 1 {
		start = 1
	}
	for page := start; page <= pages; page++ {
		count++
		if count > p.num {
			break
		}
		pList = append(pList, page)
	}
	return pList
}

func (p *Pagination) setDefault() *Pagination {
	if p.mode == ModePageNumber {
		if p.page < 1 {
			p.page = 1
		}
		if p.size < 1 {
			p.size = 50
		}
		if p.num < 1 {
			p.num = 10
		}
	}
	return p
}

func (p *Pagination) Render(settings ...string) interface{} {
	p.setDefault()
	switch len(settings) {
	case 1:
		p.tmpl = settings[0]
	}
	if len(p.tmpl) == 0 {
		p.tmpl = `pagination`
	}
	b, e := p.context.Fetch(p.tmpl, p)
	if e != nil {
		return e
	}
	return template.HTML(string(b))
}

// MarshalJSON allows type Pagination to be used with json.Marshal
func (p *Pagination) MarshalJSON() ([]byte, error) {
	b, e := json.Marshal(p.data)
	var s string
	if e != nil {
		s = fmt.Sprintf(`%q`, e.Error())
	} else {
		s = engine.Bytes2str(b)
	}
	if p.mode == ModePageNumber {
		p.setDefault()
		s = fmt.Sprintf(`{"page":%d,"rows":%d,"size":%d,"limit":%d,"pages":%d,"urlLayout":%q,"data":%s}`, p.Page(), p.Rows(), p.Size(), p.Limit(), p.Pages(), p.urlLayout, s)
	} else {
		s = fmt.Sprintf(`{"curr":%q,"prev":%q,"next":%q,"urlLayout":%q,"data":%s}`, p.Position(), p.PrevPosition(), p.NextPosition(), p.urlLayout, s)
	}
	return engine.Str2bytes(s), nil
}

func (p *Pagination) SetOptions(m echo.H) *Pagination {
	if _, y := m[`page`]; y {
		p.mode = ModePageNumber
		p.page = m.Int(`page`)
		p.rows = m.Int(`rows`)
		p.size = m.Int(`size`)
		if p.size <= 0 && m.Has(`limit`) {
			p.size = m.Int(`limit`)
		}
		p.pages = m.Int(`pages`)
	} else {
		p.mode = ModePosition
		p.position = m.String(`curr`)
		p.prevPosition = m.String(`prev`)
		p.nextPosition = m.String(`next`)
	}
	p.urlLayout = m.String(`urlLayout`)
	p.data = m.Store(`data`)
	return p
}

func (p *Pagination) Options() echo.H {
	m := echo.H{}
	if p.mode == ModePageNumber {
		m.Set(`page`, p.page)
		m.Set(`rows`, p.rows)
		m.Set(`size`, p.size)
		m.Set(`limit`, p.size)
		m.Set(`pages`, p.pages)
	} else {
		m.Set(`curr`, p.position)
		m.Set(`prev`, p.prevPosition)
		m.Set(`next`, p.nextPosition)
	}
	m.Set(`urlLayout`, p.urlLayout)
	m.Set(`data`, p.data)
	return m
}

// MarshalXML allows type Pagination to be used with xml.Marshal
func (p *Pagination) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	start.Name.Local = `Pagination`
	if err := e.EncodeToken(start); err != nil {
		return err
	}
	if p.mode == ModePageNumber {
		p.setDefault()
		if err := xmlEncode(e, `page`, p.Page()); err != nil {
			return err
		}
		if err := xmlEncode(e, `rows`, p.Rows()); err != nil {
			return err
		}
		if err := xmlEncode(e, `limit`, p.Limit()); err != nil {
			return err
		}
		if err := xmlEncode(e, `size`, p.Size()); err != nil {
			return err
		}
		if err := xmlEncode(e, `pages`, p.Pages()); err != nil {
			return err
		}
	} else {
		if err := xmlEncode(e, `curr`, p.Position()); err != nil {
			return err
		}
		if err := xmlEncode(e, `prev`, p.PrevPosition()); err != nil {
			return err
		}
		if err := xmlEncode(e, `next`, p.NextPosition()); err != nil {
			return err
		}
	}
	if err := xmlEncode(e, `urlLayout`, p.urlLayout); err != nil {
		return err
	}
	if err := xmlEncode(e, `data`, p.data); err != nil {
		return err
	}
	return e.EncodeToken(xml.EndElement{Name: start.Name})
}

func xmlEncode(e *xml.Encoder, key string, value interface{}) error {
	elem := xml.StartElement{
		Name: xml.Name{Space: ``, Local: key},
		Attr: []xml.Attr{},
	}
	return e.EncodeElement(value, elem)
}
<|endoftext|>


<commit_before>package ionic

import (
	"encoding/json"
	"fmt"
	"net/http"
	"testing"

	. "github.com/franela/goblin"
	"github.com/gomicro/bogus"
	. "github.com/onsi/gomega"
)

func TestProducts(t *testing.T) {
	g := Goblin(t)
	RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

	g.Describe("Products", func() {
		server := bogus.New()
		server.Start()
		h, p := server.HostPort()
		client, _ := New("", fmt.Sprintf("http://%v:%v", h, p))

		g.It("should get a product", func() {
			server.AddPath("/v1/vulnerability/getProducts").
				SetMethods("GET").
				SetPayload([]byte(SampleValidProduct)).
				SetStatus(http.StatusOK)

			product, err := client.GetProducts("cpe:/a:ruby-lang:ruby:1.8.7")
			Expect(err).To(BeNil())
			Expect(product[0].ID).To(Equal(99182))
			Expect(product[0].Name).To(Equal("ruby"))
		})

		g.It("should get a raw product", func() {
			server.AddPath("/v1/vulnerability/getProducts").
				SetMethods("GET").
				SetPayload([]byte(SampleValidProduct)).
				SetStatus(http.StatusOK)

			raw, err := client.GetRawProducts("cpe:/a:ruby-lang:ruby:1.8.7")
			Expect(err).To(BeNil())
			Expect(raw).To(Equal(json.RawMessage(SampleValidRawProduct)))
		})
	})
}

const (
	SampleValidProduct    = `{"data":[{"id":99182,"name":"ruby","org":"ruby-lang","version":"1.8.7","up":"","edition":"","aliases":null,"created_at":"2017-06-29T03:43:04.145Z","updated_at":"2017-06-29T03:43:04.145Z","title":"ruby-lang Ruby 1.8.7","references":[],"part":"/a","language":"","source_id":1,"external_id":"cpe:/a:ruby-lang:ruby:1.8.7","source":{"id":1,"name":"NVD","description":"National Vulnerability Database","created_at":"2017-06-29T03:41:35.919Z","updated_at":"2017-06-29T03:41:35.919Z","attribution":null,"license":null,"copyright_url":null}}]}`
	SampleValidRawProduct = `["id":99182,"name":"ruby","org":"ruby-lang","version":"1.8.7","up":"","edition":"","aliases":null,"created_at":"2017-06-29T03:43:04.145Z","updated_at":"2017-06-29T03:43:04.145Z","title":"ruby-lang Ruby 1.8.7","references":[],"part":"/a","language":"","source_id":1,"external_id":"cpe:/a:ruby-lang:ruby:1.8.7","source":{"id":1,"name":"NVD","description":"National Vulnerability Database","created_at":"2017-06-29T03:41:35.919Z","updated_at":"2017-06-29T03:41:35.919Z","attribution":null,"license":null,"copyright_url":null}]`
)
<commit_msg>correct expected json output<commit_after>package ionic

import (
	"encoding/json"
	"fmt"
	"net/http"
	"testing"

	. "github.com/franela/goblin"
	"github.com/gomicro/bogus"
	. "github.com/onsi/gomega"
)

func TestProducts(t *testing.T) {
	g := Goblin(t)
	RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

	g.Describe("Products", func() {
		server := bogus.New()
		server.Start()
		h, p := server.HostPort()
		client, _ := New("", fmt.Sprintf("http://%v:%v", h, p))

		g.It("should get a product", func() {
			server.AddPath("/v1/vulnerability/getProducts").
				SetMethods("GET").
				SetPayload([]byte(SampleValidProduct)).
				SetStatus(http.StatusOK)

			product, err := client.GetProducts("cpe:/a:ruby-lang:ruby:1.8.7")
			Expect(err).To(BeNil())
			Expect(product[0].ID).To(Equal(99182))
			Expect(product[0].Name).To(Equal("ruby"))
		})

		g.It("should get a raw product", func() {
			server.AddPath("/v1/vulnerability/getProducts").
				SetMethods("GET").
				SetPayload([]byte(SampleValidProduct)).
				SetStatus(http.StatusOK)

			raw, err := client.GetRawProducts("cpe:/a:ruby-lang:ruby:1.8.7")
			Expect(err).To(BeNil())
			Expect(raw).To(Equal(json.RawMessage(SampleValidRawProduct)))
		})
	})
}

const (
	SampleValidProduct    = `{"data":[{"id":99182,"name":"ruby","org":"ruby-lang","version":"1.8.7","up":"","edition":"","aliases":null,"created_at":"2017-06-29T03:43:04.145Z","updated_at":"2017-06-29T03:43:04.145Z","title":"ruby-lang Ruby 1.8.7","references":[],"part":"/a","language":"","source_id":1,"external_id":"cpe:/a:ruby-lang:ruby:1.8.7","source":{"id":1,"name":"NVD","description":"National Vulnerability Database","created_at":"2017-06-29T03:41:35.919Z","updated_at":"2017-06-29T03:41:35.919Z","attribution":null,"license":null,"copyright_url":null}}]}`
	SampleValidRawProduct = `[{"id":99182,"name":"ruby","org":"ruby-lang","version":"1.8.7","up":"","edition":"","aliases":null,"created_at":"2017-06-29T03:43:04.145Z","updated_at":"2017-06-29T03:43:04.145Z","title":"ruby-lang Ruby 1.8.7","references":[],"part":"/a","language":"","source_id":1,"external_id":"cpe:/a:ruby-lang:ruby:1.8.7","source":{"id":1,"name":"NVD","description":"National Vulnerability Database","created_at":"2017-06-29T03:41:35.919Z","updated_at":"2017-06-29T03:41:35.919Z","attribution":null,"license":null,"copyright_url":null}}]`
)
<|endoftext|>


<commit_before>package config

import "sync"

//Values provides storage of arbitrary interface{} values referenced by type Key.
//The zero value for Values is not in a valid state, thus Values should be
//created with NewValues().
//Values is safe for use by multiple goroutines.
type Values struct {
	lock *sync.RWMutex
	root *node
}

//NewValues creates an empty *Values.
func NewValues() *Values {
	return &Values{
		lock: &sync.RWMutex{},
		root: newNode(),
	}
}

func newValues(root *node) *Values {
	return &Values{
		lock: &sync.RWMutex{},
		root: root,
	}
}

//Merge merges all associations in other into v starting at key.
//To merge other in v at root, use an empty Key for key.
func (v *Values) Merge(key Key, other *Values) bool {
	v.lock.Lock()
	defer v.lock.Unlock()

	changed := false
	other.EachKeyValue(func(otherKey Key, value interface{}) {
		actualKey := key.Append(otherKey)
		changed = v.put(actualKey, value) || changed
	})
	return changed
}

//EachKeyValue calls visitor with each set Key value association in v.
func (v *Values) EachKeyValue(visitor func(key Key, value interface{})) {
	v.lock.RLock()
	defer v.lock.RUnlock()

	v.root.eachKeyValue(nil, visitor)
}

//Equal determines whether or not v and other contain the exact same set of
//Keys and associated values.
//Comparison on a value by value basis is done with the == operator.
func (v *Values) Equal(other *Values) bool {
	v.lock.RLock()
	defer v.lock.RUnlock()
	other.lock.RLock()
	defer other.lock.RUnlock()

	return v.root.equal(other.root)
}

//Put adds the key, value association to v.
//changed indicates whether or not this operation changes the set of associations
//in any way.
func (v *Values) Put(key Key, value interface{}) (changed bool) {
	v.lock.Lock()
	defer v.lock.Unlock()

	return v.put(key, value)
}

func (v *Values) put(key Key, value interface{}) bool {
	return v.root.put(key, value)
}

//IsEmpty determines whether or not any associated exist in v.
func (v *Values) IsEmpty() bool {
	v.lock.RLock()
	defer v.lock.RUnlock()

	return v.root.isEmpty()
}

//Get returns the value associated with key or nil if the association does not
//exist.
func (v *Values) Get(key Key) (value interface{}) {
	value, _ = v.GetOk(key)
	return value
}

//GetOk return the value associated with key.
//The return value ok indicates whether or not any value is actually stored at key.
func (v *Values) GetOk(key Key) (value interface{}, ok bool) {
	v.lock.RLock()
	defer v.lock.RUnlock()

	_, found, _ := v.root.findDescendent(nil, key, false, false)
	if found == nil {
		return nil, false
	}
	if found.isSet() {
		return found.value, true
	}
	return newValues(found.clone()), true
}

//Clone creates a new Values with all associations copied into the result.
//The individual values are shallow copied into the result.
func (v *Values) Clone() *Values {
	v.lock.RLock()
	defer v.lock.RUnlock()

	return newValues(v.root)
}

//Remove deletes the association stored at key if one exists.
//v is the removed value or nil if nothing was returned, and ok indicated any value
//was actually removed.
func (v *Values) Remove(key Key) (value interface{}, ok bool) {
	v.lock.Lock()
	defer v.lock.Unlock()

	if key.IsEmpty() {
		if v.root.isSet() {
			result := v.root.value
			v.root = newNode()
			return result, true
		}
		return nil, false
	}

	parent, found, _ := v.root.findDescendent(nil, key, false, false)
	if found == nil {
		return nil, false
	}
	var result interface{}
	if found.isSet() {
		result = found.value
	} else {
		result = newValues(found)
	}
	if parent != nil {
		delete(parent.children, key[key.Len()-1])
	}
	return result, true
}

type node struct {
	value    interface{}
	children map[string]*node
}

func newNodeValue(value interface{}) *node {
	n := newNode()
	n.value = value
	n.children = nil
	return n
}

func newNode() *node {
	return &node{
		value:    nil,
		children: map[string]*node{},
	}
}

func (n *node) isEmpty() bool {
	return !n.isSet() && len(n.children) == 0
}

func (n *node) isSet() bool {
	return n.children == nil
}

func (n *node) put(key Key, value interface{}) bool {
	if key.IsEmpty() {
		return n.setValue(value)
	}
	child, changed := n.findChild(key[0], true)
	remainingKey := key[1:]
	return child.put(remainingKey, value) || changed
}

func (n *node) setValue(value interface{}) bool {
	if values, ok := value.(*Values); ok {
		return n.setValues(values)
	}
	changed := false
	if n.isSet() {
		changed = value != n.value
	} else {
		changed = true
	}
	n.value = value
	n.children = nil
	return changed
}

func (n *node) setValues(values *Values) bool {
	if values.IsEmpty() {
		if n.isEmpty() {
			return false
		}
		n.value = nil
		n.children = nil
		return true
	}
	changed := false
	values.EachKeyValue(func(key Key, value interface{}) {
		changed = n.put(key, value) || changed
	})
	return changed
}

func (n *node) clone() *node {
	return &node{
		value:    n.value,
		children: n.cloneChildren(),
	}
}

func (n *node) cloneChildren() map[string]*node {
	if n.children == nil {
		return nil
	}
	result := map[string]*node{}
	for key, child := range n.children {
		result[key] = child.clone()
	}
	return result
}

func (n *node) eachKeyValue(key Key, visitor func(key Key, value interface{})) {
	if n.isSet() {
		visitor(key, n.value)
		return
	}
	for keyPart, childNode := range n.children {
		childNode.eachKeyValue(append(NewKey(key...), keyPart), visitor)
	}
}

func (n *node) equal(other *node) bool {
	if n.value != other.value {
		return false
	}
	return n.childrenEqual(other)
}

func (n *node) childrenEqual(other *node) bool {
	if len(n.children) != len(other.children) {
		return false
	}
	for keyPart, child := range n.children {
		otherChild, ok := other.children[keyPart]
		if !ok || !child.equal(otherChild) {
			return false
		}
	}
	return true
}

func (n *node) findDescendent(parent *node, key Key, canChange, hasChanged bool) (*node, *node, bool) {
	if key.IsEmpty() {
		return parent, n, hasChanged
	}
	child, changed := n.findChild(key[0], canChange)
	if child == nil {
		return parent, nil, changed
	}
	return child.findDescendent(n, key[1:], canChange, changed || hasChanged)
}

func (n *node) findChild(keyPart string, canChange bool) (*node, bool) {
	changed := false
	if n.isSet() {
		if !canChange {
			return nil, false
		}
		n.value, changed = nil, true
		n.children = map[string]*node{}
	}
	child, ok := n.children[keyPart]
	if !ok {
		if !canChange {
			return nil, false
		}
		n.children[keyPart] = newNode()
		child = n.children[keyPart]
		changed = true
	}
	return child, changed
}
<commit_msg>Adds documentation.<commit_after>package config

import "sync"

//Values provides storage of arbitrary interface{} values referenced by type Key.
//The zero value for Values is not in a valid state, thus Values should be
//created with NewValues().
//Values is safe for use by multiple goroutines.
type Values struct {
	lock *sync.RWMutex
	root *node
}

//NewValues creates an empty *Values.
func NewValues() *Values {
	return &Values{
		lock: &sync.RWMutex{},
		root: newNode(),
	}
}

func newValues(root *node) *Values {
	return &Values{
		lock: &sync.RWMutex{},
		root: root,
	}
}

//Merge merges all associations in other into v starting at key.
//To merge other in v at root, use an empty Key for key.
func (v *Values) Merge(key Key, other *Values) bool {
	v.lock.Lock()
	defer v.lock.Unlock()

	changed := false
	other.EachKeyValue(func(otherKey Key, value interface{}) {
		actualKey := key.Append(otherKey)
		changed = v.put(actualKey, value) || changed
	})
	return changed
}

//EachKeyValue calls visitor with each set Key value association in v.
func (v *Values) EachKeyValue(visitor func(key Key, value interface{})) {
	v.lock.RLock()
	defer v.lock.RUnlock()

	v.root.eachKeyValue(nil, visitor)
}

//Equal determines whether or not v and other contain the exact same set of
//Keys and associated values.
//Comparison on a value by value basis is done with the == operator.
func (v *Values) Equal(other *Values) bool {
	v.lock.RLock()
	defer v.lock.RUnlock()
	other.lock.RLock()
	defer other.lock.RUnlock()

	return v.root.equal(other.root)
}

//Put adds the key, value association to v.
//changed indicates whether or not this operation changes the set of associations
//in any way.
func (v *Values) Put(key Key, value interface{}) (changed bool) {
	v.lock.Lock()
	defer v.lock.Unlock()

	return v.put(key, value)
}

func (v *Values) put(key Key, value interface{}) bool {
	return v.root.put(key, value)
}

//IsEmpty determines whether or not any associated exist in v.
func (v *Values) IsEmpty() bool {
	v.lock.RLock()
	defer v.lock.RUnlock()

	return v.root.isEmpty()
}

//Get returns the value associated with key or nil if the association does not
//exist.
func (v *Values) Get(key Key) (value interface{}) {
	value, _ = v.GetOk(key)
	return value
}

//GetOk return the value associated with key.
//The return value ok indicates whether or not any value is actually stored at key.
func (v *Values) GetOk(key Key) (value interface{}, ok bool) {
	v.lock.RLock()
	defer v.lock.RUnlock()

	_, found, _ := v.root.findDescendent(nil, key, false, false)
	if found == nil {
		return nil, false
	}
	if found.isSet() {
		return found.value, true
	}
	return newValues(found.clone()), true
}

//Clone creates a new Values with all associations copied into the result.
//The individual values are shallow copied into the result.
func (v *Values) Clone() *Values {
	v.lock.RLock()
	defer v.lock.RUnlock()

	return newValues(v.root)
}

//Remove deletes the association stored at key if one exists.
//v is the removed value or nil if nothing was returned, and ok indicated any value
//was actually removed.
func (v *Values) Remove(key Key) (value interface{}, ok bool) {
	v.lock.Lock()
	defer v.lock.Unlock()

	if key.IsEmpty() {
		if v.root.isSet() {
			result := v.root.value
			v.root = newNode()
			return result, true
		}
		return nil, false
	}

	parent, found, _ := v.root.findDescendent(nil, key, false, false)
	if found == nil {
		return nil, false
	}
	var result interface{}
	if found.isSet() {
		result = found.value
	} else {
		result = newValues(found)
	}
	if parent != nil {
		delete(parent.children, key[key.Len()-1])
	}
	return result, true
}

//node is the internal node type for a Values tree.
//It stores the value stored at its location in the tree and links to children node.
type node struct {
	//value is the value stored at this location in the tree.
	//It may be nil.
	//It is determined to be set by the isSet() method.
	value interface{}

	//children holds the references to this node's child nodes.
	//The keys in children are the parts to the larger Key that references a value.
	children map[string]*node
}

func newNodeValue(value interface{}) *node {
	n := newNode()
	n.value = value
	n.children = nil
	return n
}

func newNode() *node {
	return &node{
		value:    nil,
		children: map[string]*node{},
	}
}

func (n *node) isEmpty() bool {
	return !n.isSet() && len(n.children) == 0
}

func (n *node) isSet() bool {
	return n.children == nil
}

func (n *node) put(key Key, value interface{}) bool {
	if key.IsEmpty() {
		return n.setValue(value)
	}
	child, changed := n.findChild(key[0], true)
	remainingKey := key[1:]
	return child.put(remainingKey, value) || changed
}

func (n *node) setValue(value interface{}) bool {
	if values, ok := value.(*Values); ok {
		return n.setValues(values)
	}
	changed := false
	if n.isSet() {
		changed = value != n.value
	} else {
		changed = true
	}
	n.value = value
	n.children = nil
	return changed
}

func (n *node) setValues(values *Values) bool {
	if values.IsEmpty() {
		if n.isEmpty() {
			return false
		}
		n.value = nil
		n.children = nil
		return true
	}
	changed := false
	values.EachKeyValue(func(key Key, value interface{}) {
		changed = n.put(key, value) || changed
	})
	return changed
}

func (n *node) clone() *node {
	return &node{
		value:    n.value,
		children: n.cloneChildren(),
	}
}

func (n *node) cloneChildren() map[string]*node {
	if n.children == nil {
		return nil
	}
	result := map[string]*node{}
	for key, child := range n.children {
		result[key] = child.clone()
	}
	return result
}

func (n *node) eachKeyValue(key Key, visitor func(key Key, value interface{})) {
	if n.isSet() {
		visitor(key, n.value)
		return
	}
	for keyPart, childNode := range n.children {
		childNode.eachKeyValue(append(NewKey(key...), keyPart), visitor)
	}
}

func (n *node) equal(other *node) bool {
	if n.value != other.value {
		return false
	}
	return n.childrenEqual(other)
}

func (n *node) childrenEqual(other *node) bool {
	if len(n.children) != len(other.children) {
		return false
	}
	for keyPart, child := range n.children {
		otherChild, ok := other.children[keyPart]
		if !ok || !child.equal(otherChild) {
			return false
		}
	}
	return true
}

func (n *node) findDescendent(parent *node, key Key, canChange, hasChanged bool) (*node, *node, bool) {
	if key.IsEmpty() {
		return parent, n, hasChanged
	}
	child, changed := n.findChild(key[0], canChange)
	if child == nil {
		return parent, nil, changed
	}
	return child.findDescendent(n, key[1:], canChange, changed || hasChanged)
}

func (n *node) findChild(keyPart string, canChange bool) (*node, bool) {
	changed := false
	if n.isSet() {
		if !canChange {
			return nil, false
		}
		n.value, changed = nil, true
		n.children = map[string]*node{}
	}
	child, ok := n.children[keyPart]
	if !ok {
		if !canChange {
			return nil, false
		}
		n.children[keyPart] = newNode()
		child = n.children[keyPart]
		changed = true
	}
	return child, changed
}
<|endoftext|>


<commit_before>package netchan

import "runtime"

// SelectRecv loops on multiple receivers until it gets a value, it will
// return nil, nil if block==false and there was nothing to receive
func SelectRecv(block bool, recvs []Receiver) (Receiver, interface{}) {
	for {
		for _, ch := range recvs {
			_, val, st := ch.Recv(false)
			if st == StatusOK {
				return ch, val
			}
		}
		if !block {
			return nil, nil
		}
		runtime.Gosched()
	}
}

// SelectSend loops on multiple senders and returns the first channel that
// was able to send or nil if block == false and nothing was sent.
func SelectSend(block bool, targets []Sender, val interface{}) Sender {
	for {
		for _, ch := range targets {
			st := ch.Send(false, val)
			if st == StatusOK {
				return ch
			}
		}
		if !block {
			return nil
		}
		runtime.Gosched()
	}
}
<commit_msg>now Select uses reflect.Select, so it always block now<commit_after>package netchan

import "reflect"

// SelectRecv loops on multiple receivers until it gets a value,
// it blocks until a value is returned or all channels are closed.
// this function doesn't panic.
func SelectRecv(recvs []Receiver) (r Receiver, val interface{}) {
	defer func() {
		if recover() != nil {
			r = nil
			val = nil
		}
	}()
	cases := make([]reflect.SelectCase, len(recvs))
	for i, rch := range recvs {
		cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv}
		switch rch := rch.(type) {
		case Channel:
			cases[i].Chan = reflect.ValueOf(rch.r)
		case LocalReceiver:
			cases[i].Chan = reflect.ValueOf((<-chan interface{})(rch))
		default:
			panic("SelectRecv only supports Channel and/or LocalReceiver")
		}
	}
	i, v, ok := reflect.Select(cases)
	if ok {
		r = recvs[i]
		val = v.Interface()
		if val, ok := val.(*pkt); ok {
			return r, val.Value
		}
		return
	}
	return
}

// SelectSend loops on multiple senders and returns the first channel that
// was able to send.
// it returns the target that sent the value or returns nil if all channels were closed
// this function doesn't panic.
func SelectSend(targets []Sender, val interface{}) (sch Sender) {
	defer func() {
		if recover() != nil {
			sch = nil
		}
	}()
	cases := make([]reflect.SelectCase, len(targets))
	p := reflect.ValueOf(&pkt{Type: pktData, Value: val})
	for i, sch := range targets {
		cases[i] = reflect.SelectCase{Dir: reflect.SelectSend}
		switch sch := sch.(type) {
		case Channel:
			cases[i].Chan = reflect.ValueOf(sch.s)
			cases[i].Send = p
		case LocalSender:
			cases[i].Chan = reflect.ValueOf((chan<- interface{})(sch))
			cases[i].Send = reflect.ValueOf(val)
		default:
			panic("SelectSend only supports Channel and/or LocalSender")
		}
	}
	i, _, _ := reflect.Select(cases)
	return targets[i]
}
<|endoftext|>


<commit_before>package chem

import (
	"database/sql"
	"fmt"
	"reflect"
	"strings"
)

type SelectStmt struct {
	columns []Column
	filters []Filter
}

func Select(columnThings ...Columnser) SelectStmt {
	columns := make([]Column, 0, len(columnThings))
	for _, c := range columnThings {
		columns = append(columns, c.Columns()...)
	}

	return SelectStmt{columns: columns}
}

func (s SelectStmt) Where(filters ...Filter) SelectStmt {
	s.filters = filters
	return s
}

func toTableNames(columns []Column) []string {
	names := make(map[string]bool)
	for _, c := range columns {
		names[c.Table().Name()] = true
	}
	nameList := make([]string, 0, len(names))
	for name := range names {
		nameList = append(nameList, name)
	}
	return nameList
}

func toColumnExpressions(columns []Column) (out []string) {
	for _, c := range columns {
		out = append(out, c.toColumnExpression())
	}
	return
}

func toBooleanExpressions(filters []Filter) (out []string) {
	for _, filter := range filters {
		out = append(out, filter.toBooleanExpression())
	}
	return
}

func flattenValues(values []interface{}) []interface{} {
	out := make([]interface{}, 0, len(values))
	flattened := false

	for _, value := range values {
		reflection := reflect.ValueOf(value).Elem()
		reflectType := reflection.Type()
		switch reflectType.Kind() {
		case reflect.Struct:
			for i := 0; i < reflection.NumField(); i++ {
				out = append(out, reflection.Field(i).Addr().Interface())
			}
			flattened = true
		default:
			out = append(out, value)
		}
	}
	// if we ever flattened any structs, there could be nested structs, so let's recurse
	if flattened {
		return flattenValues(out)
	}
	// otherwise we're done
	return out
}

func makeWhereClause(f Filter) string {
	expression := f.toBooleanExpression()
	if expression == "" {
		return ""
	}
	return fmt.Sprintf("WHERE %v", expression)
}

func (s SelectStmt) constructSQL() string {
	return strings.Join(
		filterStringSlice(
			fmt.Sprintf(
				"SELECT %v FROM %v",
				strings.Join(toColumnExpressions(s.columns), ", "),
				strings.Join(toTableNames(s.columns), ", "),
			),
			makeWhereClause(AND(s.filters...)),
		),
		" ",
	)
}

func (s SelectStmt) One(tx *sql.Tx, values ...interface{}) error {
	return tx.QueryRow(
		s.constructSQL(),
		AND(s.filters...).binds()...,
	).Scan(flattenValues(values)...)
}
<commit_msg>add comment to flattenValues<commit_after>package chem

import (
	"database/sql"
	"fmt"
	"reflect"
	"strings"
)

type SelectStmt struct {
	columns []Column
	filters []Filter
}

func Select(columnThings ...Columnser) SelectStmt {
	columns := make([]Column, 0, len(columnThings))
	for _, c := range columnThings {
		columns = append(columns, c.Columns()...)
	}

	return SelectStmt{columns: columns}
}

func (s SelectStmt) Where(filters ...Filter) SelectStmt {
	s.filters = filters
	return s
}

func toTableNames(columns []Column) []string {
	names := make(map[string]bool)
	for _, c := range columns {
		names[c.Table().Name()] = true
	}
	nameList := make([]string, 0, len(names))
	for name := range names {
		nameList = append(nameList, name)
	}
	return nameList
}

func toColumnExpressions(columns []Column) (out []string) {
	for _, c := range columns {
		out = append(out, c.toColumnExpression())
	}
	return
}

func toBooleanExpressions(filters []Filter) (out []string) {
	for _, filter := range filters {
		out = append(out, filter.toBooleanExpression())
	}
	return
}

func flattenValues(values []interface{}) []interface{} {
	out := make([]interface{}, 0, len(values))
	flattened := false

	for _, value := range values {
		reflection := reflect.ValueOf(value).Elem()
		reflectType := reflection.Type()
		switch reflectType.Kind() {
		case reflect.Struct:
			for i := 0; i < reflection.NumField(); i++ {
				// flatten this struct into pointers to each field of it
				out = append(out, reflection.Field(i).Addr().Interface())
			}
			flattened = true
		default:
			out = append(out, value)
		}
	}
	// if we ever flattened any structs, there could be nested structs, so let's recurse
	if flattened {
		return flattenValues(out)
	}
	// otherwise we're done
	return out
}

func makeWhereClause(f Filter) string {
	expression := f.toBooleanExpression()
	if expression == "" {
		return ""
	}
	return fmt.Sprintf("WHERE %v", expression)
}

func (s SelectStmt) constructSQL() string {
	return strings.Join(
		filterStringSlice(
			fmt.Sprintf(
				"SELECT %v FROM %v",
				strings.Join(toColumnExpressions(s.columns), ", "),
				strings.Join(toTableNames(s.columns), ", "),
			),
			makeWhereClause(AND(s.filters...)),
		),
		" ",
	)
}

func (s SelectStmt) One(tx *sql.Tx, values ...interface{}) error {
	return tx.QueryRow(
		s.constructSQL(),
		AND(s.filters...).binds()...,
	).Scan(flattenValues(values)...)
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"

	"github.com/aymerick/douceur/inliner"
	"github.com/drone/drone-go/drone"
	"github.com/drone/drone-go/template"
	"github.com/go-gomail/gomail"
	"github.com/jaytaylor/html2text"
)

func Send(context *Context) error {
	payload := &drone.Payload{
		System: &context.System,
		Repo:   &context.Repo,
		Build:  &context.Build,
	}

	subject, plain, html, err := build(
		payload,
		context,
	)

	if err != nil {
		return err
	}

	return send(
		subject,
		plain,
		html,
		context,
	)
}

func build(payload *drone.Payload, context *Context) (string, string, string, error) {
	subject, err := template.RenderTrim(
		context.Vargs.Subject,
		payload)

	if err != nil {
		return "", "", "", err
	}

	body, err := template.RenderTrim(
		context.Vargs.Template,
		payload,
	)

	if err != nil {
		return "", "", "", err
	}

	html, err := inliner.Inline(body)

	if err != nil {
		return "", "", "", err
	}

	plain, err := html2text.FromString(
		html,
	)

	if err != nil {
		return "", "", "", err
	}

	return subject, plain, html, nil
}

func send(subject, plainBody, htmlBody string, c *Context) error {
	if len(c.Vargs.Recipients) == 0 {
		c.Vargs.Recipients = []string{
			c.Build.Email,
		}
	}

	m := gomail.NewMessage()

	m.SetHeader(
		"To",
		c.Vargs.Recipients...,
	)

	m.SetHeader(
		"From",
		c.Vargs.From,
	)

	m.SetHeader(
		"Subject",
		subject,
	)

	m.AddAlternative(
		"text/plain",
		plainBody,
	)

	m.AddAlternative(
		"text/html",
		htmlBody,
	)

	d := gomail.NewPlainDialer(
		c.Vargs.Host,
		c.Vargs.Port,
		c.Vargs.Username,
		c.Vargs.Password,
	)

	if c.Vargs.SkipVerify {
		d.TLSConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	return d.DialAndSend(m)
}
<commit_msg>Support email notification without SMTP auth.<commit_after>package main

import (
	"crypto/tls"

	"github.com/aymerick/douceur/inliner"
	"github.com/drone/drone-go/drone"
	"github.com/drone/drone-go/template"
	"github.com/go-gomail/gomail"
	"github.com/jaytaylor/html2text"
)

func Send(context *Context) error {
	payload := &drone.Payload{
		System: &context.System,
		Repo:   &context.Repo,
		Build:  &context.Build,
	}

	subject, plain, html, err := build(
		payload,
		context,
	)

	if err != nil {
		return err
	}

	return send(
		subject,
		plain,
		html,
		context,
	)
}

func build(payload *drone.Payload, context *Context) (string, string, string, error) {
	subject, err := template.RenderTrim(
		context.Vargs.Subject,
		payload)

	if err != nil {
		return "", "", "", err
	}

	body, err := template.RenderTrim(
		context.Vargs.Template,
		payload,
	)

	if err != nil {
		return "", "", "", err
	}

	html, err := inliner.Inline(body)

	if err != nil {
		return "", "", "", err
	}

	plain, err := html2text.FromString(
		html,
	)

	if err != nil {
		return "", "", "", err
	}

	return subject, plain, html, nil
}

func send(subject, plainBody, htmlBody string, c *Context) error {
	if len(c.Vargs.Recipients) == 0 {
		c.Vargs.Recipients = []string{
			c.Build.Email,
		}
	}

	m := gomail.NewMessage()

	m.SetHeader(
		"To",
		c.Vargs.Recipients...,
	)

	m.SetHeader(
		"From",
		c.Vargs.From,
	)

	m.SetHeader(
		"Subject",
		subject,
	)

	m.AddAlternative(
		"text/plain",
		plainBody,
	)

	m.AddAlternative(
		"text/html",
		htmlBody,
	)

	var d *gomail.Dialer
	if c.Vargs.Username == "" {
		d = &gomail.Dialer{
			Host: c.Vargs.Host,
			Port: c.Vargs.Port,
			SSL:  c.Vargs.Port == 465,
		}
	} else {
		d = gomail.NewDialer(
			c.Vargs.Host,
			c.Vargs.Port,
			c.Vargs.Username,
			c.Vargs.Password,
		)
	}

	if c.Vargs.SkipVerify {
		d.TLSConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	return d.DialAndSend(m)
}
<|endoftext|>


<commit_before>package depend

import (
	"errors"
	"net/url"

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

func SendEmail(ctx context.Context, subject, content, tos string) error {
	data := url.Values{
		"subject":   {subject},
		"content":   {content},
		"from_name": {fromName()},
		"tos":       {tos},
	}
	_, err := callService(senderService, "POST", "/email/send", data)
	if err != nil {
		return err
	}

	return nil
}

// ServiceWarning 技术服务报警
func ServiceWarning(ctx context.Context, emailInfo map[string]string, smsContent string) error {
	data := url.Values{
		"subject":   {emailInfo["subject"] + "-服务【" + from + "】"},
		"content":   {emailInfo["content"]},
		"from_name": {fromName()},
		"gename":    {"tech_services"},
	}
	if smsContent != "" {
		data.Set("send_sms", "1")
		data.Set("sms_content", smsContent)
	}
	_, err := callService(senderService, "POST", "/email/group", data)
	if err != nil {
		return err
	}

	return nil
}

// SendSms 给用户发送短信，smsTypes 默认发送通知。支持的值：00-验证码;01-通知;02-营销
func SendSms(ctx context.Context, mobile, content string, smsTypes ...string) error {
	if mobile == "" || content == "" {
		return errors.New("mobile or content is empty!")
	}

	data := url.Values{
		"mobile":  {mobile},
		"content": {content},
	}

	if len(smsTypes) > 0 {
		data.Set("sms_type", smsTypes[0])
	}

	_, err := callService(senderService, "POST", "/sms/unicast", data)
	if err != nil {
		return err
	}

	return nil
}

// SendDingtalkMsg 给员工发送钉钉消息
func SendDingtalkMsg(ctx context.Context, userid, agentid, content string, msgtypes ...string) error {
	if userid == "" || agentid == "" || content == "" {
		return errors.New("userid or agentid or content is empty!")
	}

	data := url.Values{
		"touser":  {userid},
		"agentid": {agentid},
		"content": {content},
	}

	if len(msgtypes) > 0 {
		data.Set("msgtype", msgtypes[0])
	}

	_, err := callService(senderService, "POST", "/dingtalk/send", data)
	if err != nil {
		return err
	}

	return nil
}

// SendAppMsg App push
// destType: driver 司机端；supply 供货宝；shopper 芝麻掌柜
func SendAppMsg(ctx context.Context, userid, content, iosMsg, destType string) error {
	if userid == "" || content == "" {
		return errors.New("userid or content or content is empty!")
	}

	data := url.Values{
		"userid":    {userid},
		"content":   {content},
		"ios_msg":   {iosMsg},
		"dest_type": {destType},
	}

	_, err := callService(senderService, "POST", "/dingtalk/send", data)
	if err != nil {
		return err
	}

	return nil
}

func fromName() string {
	if isPro {
		return "线上服务报警"
	}

	return "开发/测试服务报警"
}
<commit_msg>bugfix<commit_after>package depend

import (
	"errors"
	"net/url"

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

func SendEmail(ctx context.Context, subject, content, tos string) error {
	data := url.Values{
		"subject":   {subject},
		"content":   {content},
		"from_name": {fromName()},
		"tos":       {tos},
	}
	_, err := callService(senderService, "POST", "/email/send", data)
	if err != nil {
		return err
	}

	return nil
}

// ServiceWarning 技术服务报警
func ServiceWarning(ctx context.Context, emailInfo map[string]string, smsContent string) error {
	data := url.Values{
		"subject":   {emailInfo["subject"] + "-服务【" + from + "】"},
		"content":   {emailInfo["content"]},
		"from_name": {fromName()},
		"gename":    {"tech_services"},
	}
	if smsContent != "" {
		data.Set("send_sms", "1")
		data.Set("sms_content", smsContent)
	}
	_, err := callService(senderService, "POST", "/email/group", data)
	if err != nil {
		return err
	}

	return nil
}

// SendSms 给用户发送短信，smsTypes 默认发送通知。支持的值：00-验证码;01-通知;02-营销
func SendSms(ctx context.Context, mobile, content string, smsTypes ...string) error {
	if mobile == "" || content == "" {
		return errors.New("mobile or content is empty!")
	}

	data := url.Values{
		"mobile":  {mobile},
		"content": {content},
		"sp":      {"xuanwu"},
	}

	if len(smsTypes) > 0 {
		data.Set("sms_type", smsTypes[0])
	}

	_, err := callService(senderService, "POST", "/sms/unicast", data)
	if err != nil {
		return err
	}

	return nil
}

// SendDingtalkMsg 给员工发送钉钉消息
func SendDingtalkMsg(ctx context.Context, userid, agentid, content string, msgtypes ...string) error {
	if userid == "" || agentid == "" || content == "" {
		return errors.New("userid or agentid or content is empty!")
	}

	data := url.Values{
		"touser":  {userid},
		"agentid": {agentid},
		"content": {content},
	}

	if len(msgtypes) > 0 {
		data.Set("msgtype", msgtypes[0])
	}

	_, err := callService(senderService, "POST", "/dingtalk/send", data)
	if err != nil {
		return err
	}

	return nil
}

// SendAppMsg App push
// destType: driver 司机端；supply 供货宝；shopper 芝麻掌柜
func SendAppMsg(ctx context.Context, userid, content, iosMsg, destType string) error {
	if userid == "" || content == "" {
		return errors.New("userid or content or content is empty!")
	}

	data := url.Values{
		"userid":    {userid},
		"content":   {content},
		"ios_msg":   {iosMsg},
		"dest_type": {destType},
	}

	_, err := callService(senderService, "POST", "/push/unicast", data)
	if err != nil {
		return err
	}

	return nil
}

func fromName() string {
	if isPro {
		return "线上服务报警"
	}

	return "开发/测试服务报警"
}
<|endoftext|>


<commit_before>package ethchain

import (
	"container/list"
	"fmt"

	"github.com/ethereum/go-ethereum/ethcrypto"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/ethutil"
	"github.com/ethereum/go-ethereum/ethwire"
	"github.com/ethereum/go-ethereum/event"
)

// Implement our EthTest Manager
type TestManager struct {
	stateManager *StateManager
	eventMux     *event.TypeMux

	db         ethutil.Database
	txPool     *TxPool
	blockChain *BlockChain
	Blocks     []*Block
}

func (s *TestManager) IsListening() bool {
	return false
}

func (s *TestManager) IsMining() bool {
	return false
}

func (s *TestManager) PeerCount() int {
	return 0
}

func (s *TestManager) Peers() *list.List {
	return list.New()
}

func (s *TestManager) BlockChain() *BlockChain {
	return s.blockChain
}

func (tm *TestManager) TxPool() *TxPool {
	return tm.txPool
}

func (tm *TestManager) StateManager() *StateManager {
	return tm.stateManager
}

func (tm *TestManager) EventMux() *event.TypeMux {
	return tm.eventMux
}
func (tm *TestManager) Broadcast(msgType ethwire.MsgType, data []interface{}) {
	fmt.Println("Broadcast not implemented")
}

func (tm *TestManager) ClientIdentity() ethwire.ClientIdentity {
	return nil
}
func (tm *TestManager) KeyManager() *ethcrypto.KeyManager {
	return nil
}

func (tm *TestManager) Db() ethutil.Database {
	return tm.db
}

func NewTestManager() *TestManager {
	ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "ETH")

	db, err := ethdb.NewMemDatabase()
	if err != nil {
		fmt.Println("Could not create mem-db, failing")
		return nil
	}
	ethutil.Config.Db = db

	testManager := &TestManager{}
	testManager.eventMux = new(event.TypeMux)
	testManager.db = db
	testManager.txPool = NewTxPool(testManager)
	testManager.blockChain = NewBlockChain(testManager)
	testManager.stateManager = NewStateManager(testManager)

	// Start the tx pool
	testManager.txPool.Start()

	return testManager
}
<commit_msg>ethchain: fix tests<commit_after>package ethchain

import (
	"container/list"
	"fmt"

	"github.com/ethereum/go-ethereum/ethcrypto"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/ethutil"
	"github.com/ethereum/go-ethereum/ethwire"
	"github.com/ethereum/go-ethereum/event"
)

// Implement our EthTest Manager
type TestManager struct {
	stateManager *StateManager
	eventMux     *event.TypeMux

	db         ethutil.Database
	txPool     *TxPool
	blockChain *ChainManager
	Blocks     []*Block
}

func (s *TestManager) IsListening() bool {
	return false
}

func (s *TestManager) IsMining() bool {
	return false
}

func (s *TestManager) PeerCount() int {
	return 0
}

func (s *TestManager) Peers() *list.List {
	return list.New()
}

func (s *TestManager) ChainManager() *ChainManager {
	return s.blockChain
}

func (tm *TestManager) TxPool() *TxPool {
	return tm.txPool
}

func (tm *TestManager) StateManager() *StateManager {
	return tm.stateManager
}

func (tm *TestManager) EventMux() *event.TypeMux {
	return tm.eventMux
}
func (tm *TestManager) Broadcast(msgType ethwire.MsgType, data []interface{}) {
	fmt.Println("Broadcast not implemented")
}

func (tm *TestManager) ClientIdentity() ethwire.ClientIdentity {
	return nil
}
func (tm *TestManager) KeyManager() *ethcrypto.KeyManager {
	return nil
}

func (tm *TestManager) Db() ethutil.Database {
	return tm.db
}

func NewTestManager() *TestManager {
	ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "ETH")

	db, err := ethdb.NewMemDatabase()
	if err != nil {
		fmt.Println("Could not create mem-db, failing")
		return nil
	}
	ethutil.Config.Db = db

	testManager := &TestManager{}
	testManager.eventMux = new(event.TypeMux)
	testManager.db = db
	testManager.txPool = NewTxPool(testManager)
	testManager.blockChain = NewChainManager(testManager)
	testManager.stateManager = NewStateManager(testManager)

	// Start the tx pool
	testManager.txPool.Start()

	return testManager
}
<|endoftext|>


<commit_before>package graph

import (
	"os"
	"testing"
)

func TestBfs02(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_02")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs := data.Bfs(data.GetNodeByID("S"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestBfs06(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()
	data, err := FromJSON(file, "test_graph_06")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	rs := data.Bfs(data.GetNodeByID("E"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestBfs07(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()
	data, err := FromJSON(file, "test_graph_07")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	rs := data.Bfs(data.GetNodeByID("E"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestDfsStack(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_02")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs := data.DfsStack(data.GetNodeByID("S"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestDfs(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_02")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs := []*Node{}
	data.Dfs(data.GetNodeByID("S"), &rs)
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestTopologicalDag01(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_01")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag := data.TopologicalDag()
	if rs != nil || isDag {
		t.Errorf("test_graph_01 has a cycle (not a DAG). Expected nil and false but %+v %v", rs, isDag)
	}
}

func TestTopologicalDag02(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_02")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag := data.TopologicalDag()
	if rs != nil || isDag {
		t.Errorf("test_graph_02 has a cycle (not a DAG). Expected nil and false but %+v %v", rs, isDag)
	}
}

func TestTopologicalDag06(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_06")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag6 := data.TopologicalDag()
	if rs == nil || !isDag6 {
		t.Errorf("test_graph_06 has no cycle (DAG). Not expected nil or false but %+v %v", rs, isDag6)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestTopologicalDag07(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_07")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag := data.TopologicalDag()
	if rs == nil || !isDag {
		t.Errorf("test_graph_07 has no cycle (DAG). Not expected nil or false but %+v %v", rs, isDag)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestTopologicalDag08(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_08")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag := data.TopologicalDag()
	if rs != nil || isDag {
		t.Errorf("test_graph_08 has a cycle (not a DAG). Expected nil and false but %+v %v", rs, isDag)
	}
}

func TestTopologicalDag09(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_09")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag := data.TopologicalDag()
	if rs != nil || isDag {
		t.Errorf("test_graph_09 has a cycle (not a DAG). Expected nil and false but %+v %v", rs, isDag)
	}
}
<commit_msg>Add more BFS testing cases<commit_after>package graph

import (
	"os"
	"testing"
)

func TestBfs02(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_02")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs := data.Bfs(data.GetNodeByID("S"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestBfs03(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_03")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs := data.Bfs(data.GetNodeByID("S"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestBfs04(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_04")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs := data.Bfs(data.GetNodeByID("S"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestBfs05(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_05")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs := data.Bfs(data.GetNodeByID("C"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestBfs06(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()
	data, err := FromJSON(file, "test_graph_06")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	rs := data.Bfs(data.GetNodeByID("E"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestBfs07(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()
	data, err := FromJSON(file, "test_graph_07")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	rs := data.Bfs(data.GetNodeByID("E"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestDfsStack(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_02")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs := data.DfsStack(data.GetNodeByID("S"))
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestDfs(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_02")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs := []*Node{}
	data.Dfs(data.GetNodeByID("S"), &rs)
	if len(rs) != data.GetNodeSize() {
		t.Errorf("Not traversed all: %s", data)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestTopologicalDag01(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_01")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag := data.TopologicalDag()
	if rs != nil || isDag {
		t.Errorf("test_graph_01 has a cycle (not a DAG). Expected nil and false but %+v %v", rs, isDag)
	}
}

func TestTopologicalDag02(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_02")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag := data.TopologicalDag()
	if rs != nil || isDag {
		t.Errorf("test_graph_02 has a cycle (not a DAG). Expected nil and false but %+v %v", rs, isDag)
	}
}

func TestTopologicalDag06(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_06")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag6 := data.TopologicalDag()
	if rs == nil || !isDag6 {
		t.Errorf("test_graph_06 has no cycle (DAG). Not expected nil or false but %+v %v", rs, isDag6)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestTopologicalDag07(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_07")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag := data.TopologicalDag()
	if rs == nil || !isDag {
		t.Errorf("test_graph_07 has no cycle (DAG). Not expected nil or false but %+v %v", rs, isDag)
	}
	traversedNodeID := make(map[string]bool)
	for _, nd := range rs {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
		if _, ok := traversedNodeID[nd.ID]; !ok {
			traversedNodeID[nd.ID] = true
		}
	}
	if len(traversedNodeID) != data.GetNodeSize() {
		t.Errorf("Found duplicate Node ID: %+v", traversedNodeID)
	}
	for nd := range data.NodeMap {
		if nd.Color == "white" {
			t.Errorf("%v", nd)
		}
	}
}

func TestTopologicalDag08(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_08")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag := data.TopologicalDag()
	if rs != nil || isDag {
		t.Errorf("test_graph_08 has a cycle (not a DAG). Expected nil and false but %+v %v", rs, isDag)
	}
}

func TestTopologicalDag09(t *testing.T) {
	file, err := os.Open("../testdata/data.json")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}
	defer file.Close()

	data, err := FromJSON(file, "test_graph_09")
	if err != nil {
		t.Errorf("Error: %+v", err)
	}

	rs, isDag := data.TopologicalDag()
	if rs != nil || isDag {
		t.Errorf("test_graph_09 has a cycle (not a DAG). Expected nil and false but %+v %v", rs, isDag)
	}
}
<|endoftext|>