<commit_before>package engine

import (
	"fmt"
	"reflect"

//"github.com/teomat/mater/collision"
)

type GameObject struct {
	name         string
	transform    *Transform
	components   []Component
	valid        bool
	active       bool
	silentActive bool
	destoryMark  bool

	Tag     string
	Physics *Physics
	Sprite  *Sprite
}

var Nil = &BaseComponent{}

func init() {
	fmt.Print()
}

func NewGameObject(name string) *GameObject {
	g := new(GameObject)
	g.name = name
	g.transform = NewTransform(g)
	g.components = make([]Component, 0)
	g.valid = true
	g.active = true
	return g
}

func (g *GameObject) Components() []Component {
	arr := make([]Component, len(g.components))
	copy(arr, g.components)
	return arr
}

func (g *GameObject) ComponentTypeOf(typ reflect.Type) Component {
	for _, c := range g.components {
		if typ == reflect.TypeOf(c) {
			return c
		}
	}
	return Nil
}

func (g *GameObject) ComponentTypeOfi(intrfce interface{}) Component {
	typ := reflect.TypeOf(intrfce)
	for _, c := range g.components {
		if typ == reflect.TypeOf(c) {
			return c
		}
	}
	return Nil
}

func (g *GameObject) ComponentImplements(intrfce interface{}) Component {
	typ := reflect.TypeOf(intrfce).Elem()
	for _, c := range g.components {
		t := reflect.TypeOf(c)
		if t.Implements(typ) {
			return c
		}
	}
	return Nil
}

func (c *GameObject) GameObject() *GameObject {
	if c.IsValid() == false {
		return nil
	}
	return c
}

func (g *GameObject) SetName(name string) {
	g.name = name
}

func (g *GameObject) Name() string {
	return g.name
}

func (g *GameObject) Transform() *Transform {
	return g.transform
}

func (g *GameObject) IsValid() bool {
	return g.valid
}

func (g *GameObject) SetActive(active bool) {
	g.active = active
	g.silentActive = active
	if active {
		for _, c := range g.components {
			c.OnEnable()
		}
	} else {
		for _, c := range g.components {
			c.OnDisable()
		}
	}
}

func (g *GameObject) SetActiveRecursive(active bool) {
	g.SetActive(active)
	childen := g.Transform().Children()
	for _, c := range childen {
		c.GameObject().SetActiveRecursive(active)
	}
}

//Used to call OnEnable & OnDisable on object which leave the scene
func (g *GameObject) setActiveRecursiveSilent(active bool) {
	g.setActiveSilent(active)
	childen := g.Transform().Children()
	for _, c := range childen {
		c.GameObject().setActiveRecursiveSilent(active)
	}
}

//Used to call OnEnable & OnDisable on object which leave the scene
func (g *GameObject) setActiveSilent(active bool) {
	if !g.active || g.silentActive == active {
		return
	}
	g.silentActive = active
	if active {
		for _, c := range g.components {
			if c != nil {
				c.OnEnable()
			}
		}
	} else {
		for _, c := range g.components {
			if c != nil {
				c.OnDisable()
			}
		}
	}
}

//Removed object from Scene if hes in one
func (g *GameObject) RemoveFromScene() {
	if g.transform.InScene() {
		g.transform.SetParent(nil)
		GetScene().SceneBase().removeGameObject(g)
		g.setActiveRecursiveSilent(false)
		g.transform.removeFromDepthMapRecursive()
	}
}

func (g *GameObject) AddToScene() {
	if !g.transform.childOfScene {
		g.transform.SetParent(nil)
	}
}

func (g *GameObject) IsActive() bool {
	return g.active
}

func (g *GameObject) Destroy() {
	g.destoryMark = true
	g.active = false
	for _, c := range g.transform.children {
		c.gameObject.Destroy()
	}
}

func (g *GameObject) destroy() {
	l := len(g.components)
	for i := l - 1; i >= 0; i-- {
		g.components[i].OnDestroy()
		g.components[i] = nil
	}

	chs := g.transform.children
	l = len(chs)
	for i := l - 1; i >= 0; i-- {
		chs[i].GameObject().destroy()
	}

	g.RemoveFromScene()
	g.name = ""
	//g.transform = nil
	g.components = nil
	g.valid = false
	g.active = false
	g.Sprite = nil
	g.Physics = nil
}

func (g *GameObject) Clone() *GameObject {
	ng := new(GameObject)
	ng.valid = true
	ng.active = true
	ng.transform = g.transform.clone(ng)
	ng.name = g.name + ""
	ng.Tag = g.Tag
	ng.components = make([]Component, 0)

	/*
		It might be possible to make this a little faster by storing size of each Component in a map and use unsafe to copy the values instead of reflect.
		(but this is already done by reflect package so I think it will be waste of time)
	*/
	for _, c := range g.components {
		v := reflect.ValueOf(c).Elem()
		n := reflect.New(v.Type())
		n.Elem().Set(v)
		nc := n.Interface().(Component)
		nc.setGameObject(ng)
		nc.setStarted(false)
		ng.AddComponent(nc)
		nc.Clone()
	}
	return ng
}

func (g *GameObject) AddComponent(com Component) Component {
	com.onAdd(com, g)
	com.setStarted(false)
	g.components = append(g.components, com)
	return com
}

func (g *GameObject) RemoveComponent(com Component) bool {
	t := reflect.TypeOf(com)
	for i, c := range g.components {
		if t == reflect.TypeOf(c) {
			g.components = append(g.components[:i], g.components[i+1:]...)
			return true
		}
	}
	return false
}

func (g *GameObject) RemoveComponentOfType(typ reflect.Type) bool {
	for i, c := range g.components {
		if typ == reflect.TypeOf(c) {
			g.components = append(g.components[:i], g.components[i+1:]...)
			return true
		}
	}
	return false
}

func (g *GameObject) RemoveComponentsOfType(typ reflect.Type) {
	for i, c := range g.components {
		if typ == reflect.TypeOf(c) {
			g.components = append(g.components[:i], g.components[i+1:]...)
		}
	}
}
<commit_msg>Destroy is now faster.<commit_after>package engine

import (
	"fmt"
	"reflect"

//"github.com/teomat/mater/collision"
)

type GameObject struct {
	name         string
	transform    *Transform
	components   []Component
	valid        bool
	active       bool
	silentActive bool
	destoryMark  bool

	Tag     string
	Physics *Physics
	Sprite  *Sprite
}

var Nil = &BaseComponent{}

func init() {
	fmt.Print()
}

func NewGameObject(name string) *GameObject {
	g := new(GameObject)
	g.name = name
	g.transform = NewTransform(g)
	g.components = make([]Component, 0)
	g.valid = true
	g.active = true
	return g
}

func (g *GameObject) Components() []Component {
	arr := make([]Component, len(g.components))
	copy(arr, g.components)
	return arr
}

func (g *GameObject) ComponentTypeOf(typ reflect.Type) Component {
	for _, c := range g.components {
		if typ == reflect.TypeOf(c) {
			return c
		}
	}
	return Nil
}

func (g *GameObject) ComponentTypeOfi(intrfce interface{}) Component {
	typ := reflect.TypeOf(intrfce)
	for _, c := range g.components {
		if typ == reflect.TypeOf(c) {
			return c
		}
	}
	return Nil
}

func (g *GameObject) ComponentImplements(intrfce interface{}) Component {
	typ := reflect.TypeOf(intrfce).Elem()
	for _, c := range g.components {
		t := reflect.TypeOf(c)
		if t.Implements(typ) {
			return c
		}
	}
	return Nil
}

func (c *GameObject) GameObject() *GameObject {
	if c.IsValid() == false {
		return nil
	}
	return c
}

func (g *GameObject) SetName(name string) {
	g.name = name
}

func (g *GameObject) Name() string {
	return g.name
}

func (g *GameObject) Transform() *Transform {
	return g.transform
}

func (g *GameObject) IsValid() bool {
	return g.valid
}

func (g *GameObject) SetActive(active bool) {
	g.active = active
	g.silentActive = active
	if active {
		for _, c := range g.components {
			c.OnEnable()
		}
	} else {
		for _, c := range g.components {
			c.OnDisable()
		}
	}
}

func (g *GameObject) SetActiveRecursive(active bool) {
	g.SetActive(active)
	childen := g.Transform().Children()
	for _, c := range childen {
		c.GameObject().SetActiveRecursive(active)
	}
}

//Used to call OnEnable & OnDisable on object which leave the scene
func (g *GameObject) setActiveRecursiveSilent(active bool) {
	g.setActiveSilent(active)
	childen := g.Transform().Children()
	for _, c := range childen {
		c.GameObject().setActiveRecursiveSilent(active)
	}
}

//Used to call OnEnable & OnDisable on object which leave the scene
func (g *GameObject) setActiveSilent(active bool) {
	if !g.active || g.silentActive == active {
		return
	}
	g.silentActive = active
	if active {
		for _, c := range g.components {
			if c != nil {
				c.OnEnable()
			}
		}
	} else {
		for _, c := range g.components {
			if c != nil {
				c.OnDisable()
			}
		}
	}
}

//Removed object from Scene if hes in one
func (g *GameObject) RemoveFromScene() {
	if g.transform.InScene() {
		g.transform.SetParent(nil)
		GetScene().SceneBase().removeGameObject(g)
		g.setActiveRecursiveSilent(false)
		g.transform.removeFromDepthMapRecursive()
	}
}

func (g *GameObject) AddToScene() {
	if !g.transform.childOfScene {
		g.transform.SetParent(nil)
	}
}

func (g *GameObject) IsActive() bool {
	return g.active
}

func (g *GameObject) Destroy() {
	g.destoryMark = true
	g.active = false
	for _, c := range g.transform.children {
		c.gameObject.Destroy()
	}
}

func (g *GameObject) destroy() {
	l := len(g.components)
	for i := l - 1; i >= 0; i-- {
		g.components[i].OnDestroy()
		g.components[i] = nil
	}

	chs := g.transform.children
	l = len(chs)
	for i := l - 1; i >= 0; i-- {
		chs[i].GameObject().destroy()
	}

	if g.transform.childOfScene {
		g.RemoveFromScene()
	} else if g.transform.parent != nil {
		t := g.transform
		for i, c := range t.parent.children {
			if t == c {
				t.parent.children = append(t.parent.children[:i], t.parent.children[i+1:]...)
				break
			}
		}
		g.transform.parent = nil
	}

	g.name = ""
	//g.transform = nil
	g.components = nil
	g.valid = false
	g.active = false
	g.Sprite = nil
	g.Physics = nil
}

func (g *GameObject) Clone() *GameObject {
	ng := new(GameObject)
	ng.valid = true
	ng.active = true
	ng.transform = g.transform.clone(ng)
	ng.name = g.name + ""
	ng.Tag = g.Tag
	ng.components = make([]Component, 0)

	for _, c := range g.components {
		v := reflect.ValueOf(c).Elem()
		n := reflect.New(v.Type())
		n.Elem().Set(v)
		nc := n.Interface().(Component)
		nc.setGameObject(ng)
		nc.setStarted(false)
		ng.AddComponent(nc)
		nc.Clone()
	}
	return ng
}

func (g *GameObject) AddComponent(com Component) Component {
	com.onAdd(com, g)
	com.setStarted(false)
	g.components = append(g.components, com)
	return com
}

func (g *GameObject) RemoveComponent(com Component) bool {
	t := reflect.TypeOf(com)
	for i, c := range g.components {
		if t == reflect.TypeOf(c) {
			g.components = append(g.components[:i], g.components[i+1:]...)
			return true
		}
	}
	return false
}

func (g *GameObject) RemoveComponentOfType(typ reflect.Type) bool {
	for i, c := range g.components {
		if typ == reflect.TypeOf(c) {
			g.components = append(g.components[:i], g.components[i+1:]...)
			return true
		}
	}
	return false
}

func (g *GameObject) RemoveComponentsOfType(typ reflect.Type) {
	for i, c := range g.components {
		if typ == reflect.TypeOf(c) {
			g.components = append(g.components[:i], g.components[i+1:]...)
		}
	}
}
<|endoftext|>


<commit_before>package workload

import (
	"context"
	"fmt"
	"reflect"

	"strings"

	"github.com/rancher/types/apis/core/v1"
	"github.com/rancher/types/config"
	"github.com/sirupsen/logrus"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// This controller is responsible for monitoring workloads and
// creating services for them
// a) when rancher ports annotation is present, create service based on annotation ports
// b) when annotation is missing, create a headless service

type Controller struct {
	workloadController CommonController
	serviceLister      v1.ServiceLister
	services           v1.ServiceInterface
}

func Register(ctx context.Context, workload *config.UserOnlyContext) {
	c := &Controller{
		serviceLister: workload.Core.Services("").Controller().Lister(),
		services:      workload.Core.Services(""),
	}
	c.workloadController = NewWorkloadController(workload, c.CreateService)
}

func getName() string {
	return "workloadServiceGenerationController"
}

func (c *Controller) CreateService(key string, w *Workload) error {
	// do not create service for job, cronJob and for workload owned by controller (ReplicaSet)
	if strings.EqualFold(w.Kind, "job") || strings.EqualFold(w.Kind, "cronJob") {
		return nil
	}
	for _, o := range w.OwnerReferences {
		if *o.Controller {
			return nil
		}
	}
	return c.CreateServiceForWorkload(w)
}

func (c *Controller) serviceExistsForWorkload(workload *Workload, service *Service) (*corev1.Service, error) {
	labels := fmt.Sprintf("%s=%s", WorkloadLabel, workload.Namespace)
	services, err := c.services.List(metav1.ListOptions{LabelSelector: labels})
	if err != nil {
		return nil, err
	}

	for _, s := range services.Items {
		if s.DeletionTimestamp != nil {
			continue
		}
		if s.Spec.Type != service.Type {
			continue
		}
		for _, ref := range s.OwnerReferences {
			if reflect.DeepEqual(ref.UID, workload.UUID) {
				return &s, nil
			}
		}
	}
	return nil, nil
}

func (c *Controller) CreateServiceForWorkload(workload *Workload) error {
	services := map[corev1.ServiceType]Service{}
	if val, ok := workload.TemplateSpec.Annotations[PortsAnnotation]; ok {
		svcs, err := generateServicesFromPortsAnnotation(val)
		if err != nil {
			return err
		}
		for _, service := range svcs {
			services[service.Type] = service
		}
	} else {
		service := generateServiceFromContainers(workload)
		services[service.Type] = *service
	}

	for _, toCreate := range services {
		existing, err := c.serviceExistsForWorkload(workload, &toCreate)
		if err != nil {
			return err
		}
		if existing == nil {
			if err := c.createService(toCreate, workload); err != nil {
				return err
			}

		} else {
			if arePortsEqual(toCreate.ServicePorts, existing.Spec.Ports) {
				continue
			}
			if err := c.updateService(toCreate, existing); err != nil {
				return err
			}
		}
	}

	return nil
}

func (c *Controller) updateService(toUpdate Service, existing *corev1.Service) error {
	existing.Spec.Ports = toUpdate.ServicePorts
	logrus.Infof("Updating [%s/%s] service with ports [%v]", existing.Namespace, existing.Name, toUpdate.ServicePorts)
	_, err := c.services.Update(existing)
	if err != nil {
		return err
	}
	return nil
}

func (c *Controller) createService(toCreate Service, workload *Workload) error {
	controller := true
	ownerRef := metav1.OwnerReference{
		Name:       workload.Name,
		APIVersion: workload.APIVersion,
		UID:        workload.UUID,
		Kind:       workload.Kind,
		Controller: &controller,
	}

	// labels are used so it is easy to filter out the service when query from API
	serviceLabels := map[string]string{}
	serviceLabels[WorkloadLabel] = workload.Namespace

	service := &corev1.Service{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName:    "workload-",
			OwnerReferences: []metav1.OwnerReference{ownerRef},
			Namespace:       workload.Namespace,
			Labels:          serviceLabels,
		},
		Spec: corev1.ServiceSpec{
			ClusterIP: toCreate.ClusterIP,
			Type:      toCreate.Type,
			Ports:     toCreate.ServicePorts,
			Selector:  workload.SelectorLabels,
		},
	}

	logrus.Infof("Creating [%s] service with ports [%v] for workload %s", service.Spec.Type, toCreate.ServicePorts, workload.getKey())
	_, err := c.services.Create(service)
	if err != nil {
		return err
	}
	return nil
}

func arePortsEqual(one []corev1.ServicePort, two []corev1.ServicePort) bool {
	if len(one) != len(two) {
		return false
	}

	for _, o := range one {
		found := false
		for _, t := range two {
			if o.TargetPort == t.TargetPort && o.Protocol == t.Protocol && o.Port == t.Port {
				found = true
				break
			}
		}
		if !found {
			return false
		}
	}

	return true
}
<commit_msg>Enable workload services in the UI<commit_after>package workload

import (
	"context"
	"fmt"
	"reflect"

	"strings"

	"github.com/rancher/types/apis/core/v1"
	"github.com/rancher/types/config"
	"github.com/sirupsen/logrus"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// This controller is responsible for monitoring workloads and
// creating services for them
// a) when rancher ports annotation is present, create service based on annotation ports
// b) when annotation is missing, create a headless service

type Controller struct {
	workloadController CommonController
	serviceLister      v1.ServiceLister
	services           v1.ServiceInterface
}

func Register(ctx context.Context, workload *config.UserOnlyContext) {
	c := &Controller{
		serviceLister: workload.Core.Services("").Controller().Lister(),
		services:      workload.Core.Services(""),
	}
	c.workloadController = NewWorkloadController(workload, c.CreateService)
}

func getName() string {
	return "workloadServiceGenerationController"
}

func (c *Controller) CreateService(key string, w *Workload) error {
	// do not create service for job, cronJob and for workload owned by controller (ReplicaSet)
	if strings.EqualFold(w.Kind, "job") || strings.EqualFold(w.Kind, "cronJob") {
		return nil
	}
	for _, o := range w.OwnerReferences {
		if *o.Controller {
			return nil
		}
	}
	return c.CreateServiceForWorkload(w)
}

func (c *Controller) serviceExistsForWorkload(workload *Workload, service *Service) (*corev1.Service, error) {
	labels := fmt.Sprintf("%s=%s", WorkloadLabel, workload.Namespace)
	services, err := c.services.List(metav1.ListOptions{LabelSelector: labels})
	if err != nil {
		return nil, err
	}

	for _, s := range services.Items {
		if s.DeletionTimestamp != nil {
			continue
		}
		if s.Spec.Type != service.Type {
			continue
		}
		for _, ref := range s.OwnerReferences {
			if reflect.DeepEqual(ref.UID, workload.UUID) {
				return &s, nil
			}
		}
	}
	return nil, nil
}

func (c *Controller) CreateServiceForWorkload(workload *Workload) error {
	services := map[corev1.ServiceType]Service{}
	if val, ok := workload.TemplateSpec.Annotations[PortsAnnotation]; ok {
		svcs, err := generateServicesFromPortsAnnotation(val)
		if err != nil {
			return err
		}
		for _, service := range svcs {
			services[service.Type] = service
		}
	} else {
		service := generateServiceFromContainers(workload)
		services[service.Type] = *service
	}

	for _, toCreate := range services {
		existing, err := c.serviceExistsForWorkload(workload, &toCreate)
		if err != nil {
			return err
		}
		if existing == nil {
			if err := c.createService(toCreate, workload); err != nil {
				return err
			}

		} else {
			if arePortsEqual(toCreate.ServicePorts, existing.Spec.Ports) {
				continue
			}
			if err := c.updateService(toCreate, existing); err != nil {
				return err
			}
		}
	}

	return nil
}

func (c *Controller) updateService(toUpdate Service, existing *corev1.Service) error {
	existing.Spec.Ports = toUpdate.ServicePorts
	logrus.Infof("Updating [%s/%s] service with ports [%v]", existing.Namespace, existing.Name, toUpdate.ServicePorts)
	_, err := c.services.Update(existing)
	if err != nil {
		return err
	}
	return nil
}

func (c *Controller) createService(toCreate Service, workload *Workload) error {
	controller := true
	ownerRef := metav1.OwnerReference{
		Name:       workload.Name,
		APIVersion: workload.APIVersion,
		UID:        workload.UUID,
		Kind:       workload.Kind,
		Controller: &controller,
	}

	// labels are used so it is easy to filter out the service when query from API
	serviceLabels := map[string]string{}
	serviceLabels[WorkloadLabel] = workload.Namespace

	service := &corev1.Service{
		ObjectMeta: metav1.ObjectMeta{
			OwnerReferences: []metav1.OwnerReference{ownerRef},
			Namespace:       workload.Namespace,
			Labels:          serviceLabels,
			Name:            workload.Name,
		},
		Spec: corev1.ServiceSpec{
			ClusterIP: toCreate.ClusterIP,
			Type:      toCreate.Type,
			Ports:     toCreate.ServicePorts,
			Selector:  workload.SelectorLabels,
		},
	}

	logrus.Infof("Creating [%s] service with ports [%v] for workload %s", service.Spec.Type, toCreate.ServicePorts, workload.getKey())
	_, err := c.services.Create(service)
	if err != nil {
		return err
	}
	return nil
}

func arePortsEqual(one []corev1.ServicePort, two []corev1.ServicePort) bool {
	if len(one) != len(two) {
		return false
	}

	for _, o := range one {
		found := false
		for _, t := range two {
			if o.TargetPort == t.TargetPort && o.Protocol == t.Protocol && o.Port == t.Port {
				found = true
				break
			}
		}
		if !found {
			return false
		}
	}

	return true
}
<|endoftext|>


<commit_before>package libgodelbrot

import (
    "log"
    "image"
    "functorama.com/demo/draw"
)

type drawFacade struct {
    picture *image.NRGBA
    colors draw.Palette
}

var _ draw.DrawingContext = (*drawFacade)(nil)
var _ draw.ContextProvider = (*drawFacade)(nil)

func (facade *drawFacade) DrawingContext() draw.DrawingContext {
    return facade
}

func (facade *drawFacade) Colors() draw.Palette {
    return facade.colors
}

func (facade *drawFacade) Picture() *image.NRGBA {
    return facade.picture
}

func makeDrawFacade(desc *Info) *drawFacade {
    facade := &drawFacade{}
    facade.colors = createPalette(desc)
    facade.picture = createImage(desc)
    return facade
}

func createImage(desc *Info) *image.NRGBA {
    req := desc.UserRequest
    bounds := image.Rectangle{
        Min: image.ZP,
        Max: image.Point{
            X: int(req.ImageWidth),
            Y: int(req.ImageHeight),
        },
    }
    return image.NewNRGBA(bounds)
}

func createStoredPalette(desc *Info) draw.Palette {
    palettes := map[string]draw.PaletteFactory{
        "redscale": draw.NewRedscalePalette,
        "pretty":   draw.NewPrettyPalette,
    }
    code := desc.UserRequest.PaletteCode
    found := palettes[code]
    if found == nil {
        log.Panic("Unknown palette:", code)
    }
    return found(desc.UserRequest.IterateLimit)
}

func createPalette(desc *Info) draw.Palette {
    req := desc.UserRequest
    // We are planning more types of palettes soon
    switch req.PaletteType {
    case StoredPalette:
        return createStoredPalette(desc)
    default:
        log.Panic("Unknown palette kind:", req.PaletteType)
    }
    return nil
}
<commit_msg>Render tasks only use grayscale drawing context<commit_after>package libgodelbrot

import (
    "image"
    "functorama.com/demo/draw"
)

type drawFacade struct {
    picture *image.NRGBA
    colors draw.Palette
}

var _ draw.DrawingContext = (*drawFacade)(nil)
var _ draw.ContextProvider = (*drawFacade)(nil)

func (facade *drawFacade) DrawingContext() draw.DrawingContext {
    return facade
}

func (facade *drawFacade) Colors() draw.Palette {
    return facade.colors
}

func (facade *drawFacade) Picture() *image.NRGBA {
    return facade.picture
}

func makeDrawFacade(desc *Info) *drawFacade {
    facade := &drawFacade{}
    facade.colors = createPalette(desc)
    facade.picture = createImage(desc)
    return facade
}

func createImage(desc *Info) *image.NRGBA {
    req := desc.UserRequest
    bounds := image.Rectangle{
        Min: image.ZP,
        Max: image.Point{
            X: int(req.ImageWidth),
            Y: int(req.ImageHeight),
        },
    }
    return image.NewNRGBA(bounds)
}

func createPalette(desc *Info) draw.Palette {
    return draw.NewGrayscalePalette(desc.UserRequest.IterateLimit)
}
<|endoftext|>


<commit_before>package wikifier

import "strings"

// CSS generates and returns the CSS code for the page's inline styles.
func (p *Page) CSS() string {
	generated := ""

	for _, style := range p.styles {
		applyTo := p.cssApplyString(style.applyTo)
		generated += applyTo + " {\n"
		for rule, value := range style.rules {
			generated += "    " + rule + ": " + value + ";\n"
		}
		generated += "}\n"
	}

	return generated
}

func (p *Page) cssApplyString(sets [][]string) string {
	parts := make([]string, len(sets))

	for i, set := range sets {
		str := p.cssSetString(set)
		var start string
		if len(str) > 9 {
			start = str[:9]
		}
		if start == "" || start != ".q-main" {
			id := p.main.el().id()
			str = ".q-" + id + " " + str
		}
		parts[i] = str
	}

	return strings.Join(parts, ",\n")
}

func (p *Page) cssSetString(set []string) string {
	for i, item := range set {
		set[i] = p.cssItemString([]rune(item))
	}
	return strings.Join(set, " ")
}

func (p *Page) cssItemString(chars []rune) string {
	var str string
	var inClass, inID, inElType bool
	for _, char := range chars {

		switch char {

		// starting a class
		case '.':
			inClass = true
			str += ".qc-"

		// starting an ID
		case '#':
			inID = true
			str += ".qi-"

		// in neither a class nor an element type
		// assume that this is the start of element type
		default:
			if !inClass && !inID && !inElType && char != '*' {
				inElType = true
				str += ".q-"
			}
			str += string(char)

		}
	}

	// return $string;
	return str
}
<commit_msg>fix bug with style{} at document level<commit_after>package wikifier

import "strings"

// CSS generates and returns the CSS code for the page's inline styles.
func (p *Page) CSS() string {
	generated := ""
	for _, style := range p.styles {
		applyTo := p.cssApplyString(style.applyTo)
		generated += applyTo + " {\n"
		for rule, value := range style.rules {
			generated += "    " + rule + ": " + value + ";\n"
		}
		generated += "}\n"
	}
	return generated
}

func (p *Page) cssApplyString(sets [][]string) string {
	parts := make([]string, len(sets))
	for i, set := range sets {
		str := p.cssSetString(set)
		if !strings.HasPrefix(str, ".q-main") {
			id := p.main.el().id()
			str = ".q-" + id + " " + str
		}
		parts[i] = str
	}
	return strings.Join(parts, ",\n")
}

func (p *Page) cssSetString(set []string) string {
	for i, item := range set {
		set[i] = p.cssItemString([]rune(item))
	}
	return strings.Join(set, " ")
}

func (p *Page) cssItemString(chars []rune) string {
	var str string
	var inClass, inID, inElType bool
	for _, char := range chars {

		switch char {

		// starting a class
		case '.':
			inClass = true
			str += ".qc-"

		// starting an ID
		case '#':
			inID = true
			str += ".qi-"

		// in neither a class nor an element type
		// assume that this is the start of element type
		default:
			if !inClass && !inID && !inElType && char != '*' {
				inElType = true
				str += ".q-"
			}
			str += string(char)

		}
	}

	// return $string;
	return str
}
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium 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 datastore

import (
	"bytes"
	"fmt"
	"strings"
)

// IndexColumn represents a sort order for a single entity field.
type IndexColumn struct {
	Property   string
	Descending bool
}

// ParseIndexColumn takes a spec in the form of /\s*-?\s*.+\s*/, and
// returns an IndexColumn. Examples are:
//   `- Field `:  IndexColumn{Property: "Field", Descending: true}
//   `Something`: IndexColumn{Property: "Something", Descending: false}
//
// `+Field` is invalid. `` is invalid.
func ParseIndexColumn(spec string) (IndexColumn, error) {
	col := IndexColumn{}
	if strings.HasPrefix(spec, "-") {
		col.Descending = true
		col.Property = strings.TrimSpace(spec[1:])
	} else if strings.HasPrefix(spec, "+") {
		return col, fmt.Errorf("datastore: invalid order: %q", spec)
	} else {
		col.Property = strings.TrimSpace(spec)
	}
	if col.Property == "" {
		return col, fmt.Errorf("datastore: empty order")
	}
	return col, nil
}

func (i IndexColumn) cmp(o IndexColumn) int {
	// sort ascending first
	if !i.Descending && o.Descending {
		return -1
	} else if i.Descending && !o.Descending {
		return 1
	}
	return cmpString(i.Property, o.Property)()
}

// String returns a human-readable version of this IndexColumn which is
// compatible with ParseIndexColumn.
func (i IndexColumn) String() string {
	ret := ""
	if i.Descending {
		ret = "-"
	}
	return ret + i.Property
}

// GQL returns a correctly formatted Cloud Datastore GQL literal which
// is valid for the `ORDER BY` clause.
//
// The flavor of GQL that this emits is defined here:
//   https://cloud.google.com/datastore/docs/apis/gql/gql_reference
func (i IndexColumn) GQL() string {
	if i.Descending {
		return gqlQuoteName(i.Property) + " DESC"
	}
	return gqlQuoteName(i.Property)
}

// IndexDefinition holds the parsed definition of a datastore index definition.
type IndexDefinition struct {
	Kind     string
	Ancestor bool
	SortBy   []IndexColumn
}

// Equal returns true if the two IndexDefinitions are equivalent.
func (id *IndexDefinition) Equal(o *IndexDefinition) bool {
	if id.Kind != o.Kind || id.Ancestor != o.Ancestor || len(id.SortBy) != len(o.SortBy) {
		return false
	}
	for i, col := range id.SortBy {
		if col != o.SortBy[i] {
			return false
		}
	}
	return true
}

// Normalize returns an IndexDefinition which has a normalized SortBy field.
//
// This is just appending __key__ if it's not explicitly the last field in this
// IndexDefinition.
func (id *IndexDefinition) Normalize() *IndexDefinition {
	if len(id.SortBy) > 0 && id.SortBy[len(id.SortBy)-1].Property == "__key__" {
		return id
	}
	ret := *id
	ret.SortBy = make([]IndexColumn, len(id.SortBy), len(id.SortBy)+1)
	copy(ret.SortBy, id.SortBy)
	ret.SortBy = append(ret.SortBy, IndexColumn{Property: "__key__"})
	return &ret
}

// GetFullSortOrder gets the full sort order for this IndexDefinition,
// including an extra "__ancestor__" column at the front if this index has
// Ancestor set to true.
func (id *IndexDefinition) GetFullSortOrder() []IndexColumn {
	id = id.Normalize()
	if !id.Ancestor {
		return id.SortBy
	}
	ret := make([]IndexColumn, 0, len(id.SortBy)+1)
	ret = append(ret, IndexColumn{Property: "__ancestor__"})
	return append(ret, id.SortBy...)
}

// PrepForIdxTable normalize and then flips the IndexDefinition.
func (id *IndexDefinition) PrepForIdxTable() *IndexDefinition {
	return id.Normalize().Flip()
}

// Flip returns an IndexDefinition with its SortBy field in reverse order.
func (id *IndexDefinition) Flip() *IndexDefinition {
	ret := *id
	ret.SortBy = make([]IndexColumn, 0, len(id.SortBy))
	for i := len(id.SortBy) - 1; i >= 0; i-- {
		ret.SortBy = append(ret.SortBy, id.SortBy[i])
	}
	return &ret
}

// Yeah who needs templates, right?
// <flames>This is fine.</flames>

func cmpBool(a, b bool) func() int {
	return func() int {
		if a == b {
			return 0
		}
		if a && !b { // >
			return 1
		}
		return -1
	}
}

func cmpInt(a, b int) func() int {
	return func() int {
		if a == b {
			return 0
		}
		if a > b {
			return 1
		}
		return -1
	}
}

func cmpString(a, b string) func() int {
	return func() int {
		if a == b {
			return 0
		}
		if a > b {
			return 1
		}
		return -1
	}
}

// Less returns true iff id is ordered before o.
func (id *IndexDefinition) Less(o *IndexDefinition) bool {
	decide := func(v int) (ret, keepGoing bool) {
		if v > 0 {
			return false, false
		}
		if v < 0 {
			return true, false
		}
		return false, true
	}

	factors := []func() int{
		cmpBool(id.Builtin(), o.Builtin()),
		cmpString(id.Kind, o.Kind),
		cmpBool(id.Ancestor, o.Ancestor),
		cmpInt(len(id.SortBy), len(o.SortBy)),
	}
	for _, f := range factors {
		ret, keepGoing := decide(f())
		if !keepGoing {
			return ret
		}
	}
	for idx := range id.SortBy {
		ret, keepGoing := decide(id.SortBy[idx].cmp(o.SortBy[idx]))
		if !keepGoing {
			return ret
		}
	}
	return false
}

// Builtin returns true iff the IndexDefinition is one of the automatic built-in
// indexes.
func (id *IndexDefinition) Builtin() bool {
	return !id.Ancestor && len(id.SortBy) <= 1
}

// Compound returns true iff this IndexDefinition is a valid compound index
// definition.
//
// NOTE: !Builtin() does not imply Compound().
func (id *IndexDefinition) Compound() bool {
	if id.Kind == "" || len(id.SortBy) <= 1 {
		return false
	}
	for _, sb := range id.SortBy {
		if sb.Property == "" || sb.Property == "__ancestor__" {
			return false
		}
	}
	return true
}

func (id *IndexDefinition) String() string {
	ret := &bytes.Buffer{}
	wr := func(r rune) {
		_, err := ret.WriteRune(r)
		if err != nil {
			panic(err)
		}
	}

	ws := func(s string) {
		_, err := ret.WriteString(s)
		if err != nil {
			panic(err)
		}
	}

	if id.Builtin() {
		wr('B')
	} else {
		wr('C')
	}
	wr(':')
	ws(id.Kind)
	if id.Ancestor {
		ws("|A")
	}
	for _, sb := range id.SortBy {
		wr('/')
		if sb.Descending {
			wr('-')
		}
		ws(sb.Property)
	}
	return ret.String()
}
<commit_msg>Fix minor bug in ParseIndexColumn<commit_after>// Copyright 2015 The Chromium 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 datastore

import (
	"bytes"
	"fmt"
	"strings"
)

// IndexColumn represents a sort order for a single entity field.
type IndexColumn struct {
	Property   string
	Descending bool
}

// ParseIndexColumn takes a spec in the form of /\s*-?\s*.+\s*/, and
// returns an IndexColumn. Examples are:
//   `- Field `:  IndexColumn{Property: "Field", Descending: true}
//   `Something`: IndexColumn{Property: "Something", Descending: false}
//
// `+Field` is invalid. `` is invalid.
func ParseIndexColumn(spec string) (IndexColumn, error) {
	col := IndexColumn{}
	spec = strings.TrimSpace(spec)
	if strings.HasPrefix(spec, "-") {
		col.Descending = true
		col.Property = strings.TrimSpace(spec[1:])
	} else if strings.HasPrefix(spec, "+") {
		return col, fmt.Errorf("datastore: invalid order: %q", spec)
	} else {
		col.Property = strings.TrimSpace(spec)
	}
	if col.Property == "" {
		return col, fmt.Errorf("datastore: empty order: %q", spec)
	}
	return col, nil
}

func (i IndexColumn) cmp(o IndexColumn) int {
	// sort ascending first
	if !i.Descending && o.Descending {
		return -1
	} else if i.Descending && !o.Descending {
		return 1
	}
	return cmpString(i.Property, o.Property)()
}

// String returns a human-readable version of this IndexColumn which is
// compatible with ParseIndexColumn.
func (i IndexColumn) String() string {
	ret := ""
	if i.Descending {
		ret = "-"
	}
	return ret + i.Property
}

// GQL returns a correctly formatted Cloud Datastore GQL literal which
// is valid for the `ORDER BY` clause.
//
// The flavor of GQL that this emits is defined here:
//   https://cloud.google.com/datastore/docs/apis/gql/gql_reference
func (i IndexColumn) GQL() string {
	if i.Descending {
		return gqlQuoteName(i.Property) + " DESC"
	}
	return gqlQuoteName(i.Property)
}

// IndexDefinition holds the parsed definition of a datastore index definition.
type IndexDefinition struct {
	Kind     string
	Ancestor bool
	SortBy   []IndexColumn
}

// Equal returns true if the two IndexDefinitions are equivalent.
func (id *IndexDefinition) Equal(o *IndexDefinition) bool {
	if id.Kind != o.Kind || id.Ancestor != o.Ancestor || len(id.SortBy) != len(o.SortBy) {
		return false
	}
	for i, col := range id.SortBy {
		if col != o.SortBy[i] {
			return false
		}
	}
	return true
}

// Normalize returns an IndexDefinition which has a normalized SortBy field.
//
// This is just appending __key__ if it's not explicitly the last field in this
// IndexDefinition.
func (id *IndexDefinition) Normalize() *IndexDefinition {
	if len(id.SortBy) > 0 && id.SortBy[len(id.SortBy)-1].Property == "__key__" {
		return id
	}
	ret := *id
	ret.SortBy = make([]IndexColumn, len(id.SortBy), len(id.SortBy)+1)
	copy(ret.SortBy, id.SortBy)
	ret.SortBy = append(ret.SortBy, IndexColumn{Property: "__key__"})
	return &ret
}

// GetFullSortOrder gets the full sort order for this IndexDefinition,
// including an extra "__ancestor__" column at the front if this index has
// Ancestor set to true.
func (id *IndexDefinition) GetFullSortOrder() []IndexColumn {
	id = id.Normalize()
	if !id.Ancestor {
		return id.SortBy
	}
	ret := make([]IndexColumn, 0, len(id.SortBy)+1)
	ret = append(ret, IndexColumn{Property: "__ancestor__"})
	return append(ret, id.SortBy...)
}

// PrepForIdxTable normalize and then flips the IndexDefinition.
func (id *IndexDefinition) PrepForIdxTable() *IndexDefinition {
	return id.Normalize().Flip()
}

// Flip returns an IndexDefinition with its SortBy field in reverse order.
func (id *IndexDefinition) Flip() *IndexDefinition {
	ret := *id
	ret.SortBy = make([]IndexColumn, 0, len(id.SortBy))
	for i := len(id.SortBy) - 1; i >= 0; i-- {
		ret.SortBy = append(ret.SortBy, id.SortBy[i])
	}
	return &ret
}

// Yeah who needs templates, right?
// <flames>This is fine.</flames>

func cmpBool(a, b bool) func() int {
	return func() int {
		if a == b {
			return 0
		}
		if a && !b { // >
			return 1
		}
		return -1
	}
}

func cmpInt(a, b int) func() int {
	return func() int {
		if a == b {
			return 0
		}
		if a > b {
			return 1
		}
		return -1
	}
}

func cmpString(a, b string) func() int {
	return func() int {
		if a == b {
			return 0
		}
		if a > b {
			return 1
		}
		return -1
	}
}

// Less returns true iff id is ordered before o.
func (id *IndexDefinition) Less(o *IndexDefinition) bool {
	decide := func(v int) (ret, keepGoing bool) {
		if v > 0 {
			return false, false
		}
		if v < 0 {
			return true, false
		}
		return false, true
	}

	factors := []func() int{
		cmpBool(id.Builtin(), o.Builtin()),
		cmpString(id.Kind, o.Kind),
		cmpBool(id.Ancestor, o.Ancestor),
		cmpInt(len(id.SortBy), len(o.SortBy)),
	}
	for _, f := range factors {
		ret, keepGoing := decide(f())
		if !keepGoing {
			return ret
		}
	}
	for idx := range id.SortBy {
		ret, keepGoing := decide(id.SortBy[idx].cmp(o.SortBy[idx]))
		if !keepGoing {
			return ret
		}
	}
	return false
}

// Builtin returns true iff the IndexDefinition is one of the automatic built-in
// indexes.
func (id *IndexDefinition) Builtin() bool {
	return !id.Ancestor && len(id.SortBy) <= 1
}

// Compound returns true iff this IndexDefinition is a valid compound index
// definition.
//
// NOTE: !Builtin() does not imply Compound().
func (id *IndexDefinition) Compound() bool {
	if id.Kind == "" || len(id.SortBy) <= 1 {
		return false
	}
	for _, sb := range id.SortBy {
		if sb.Property == "" || sb.Property == "__ancestor__" {
			return false
		}
	}
	return true
}

func (id *IndexDefinition) String() string {
	ret := &bytes.Buffer{}
	wr := func(r rune) {
		_, err := ret.WriteRune(r)
		if err != nil {
			panic(err)
		}
	}

	ws := func(s string) {
		_, err := ret.WriteString(s)
		if err != nil {
			panic(err)
		}
	}

	if id.Builtin() {
		wr('B')
	} else {
		wr('C')
	}
	wr(':')
	ws(id.Kind)
	if id.Ancestor {
		ws("|A")
	}
	for _, sb := range id.SortBy {
		wr('/')
		if sb.Descending {
			wr('-')
		}
		ws(sb.Property)
	}
	return ret.String()
}
<|endoftext|>


<commit_before>package echo

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"
	"unicode"

	"github.com/webx-top/tagfast"
	"github.com/webx-top/validation"
)

var DefaultHtmlFilter = func(v string) (r string) {
	return v
}

type (
	// Binder is the interface that wraps the Bind method.
	Binder interface {
		Bind(interface{}, Context) error
		MustBind(interface{}, Context) error
	}
	binder struct {
		*Echo
	}
)

func (b *binder) MustBind(i interface{}, c Context) (err error) {
	r := c.Request()
	body := r.Body()
	if body == nil {
		err = NewHTTPError(http.StatusBadRequest, "Request body can't be nil")
		return
	}
	defer body.Close()
	ct := r.Header().Get(HeaderContentType)
	err = ErrUnsupportedMediaType
	if strings.HasPrefix(ct, MIMEApplicationJSON) {
		err = json.NewDecoder(body).Decode(i)
	} else if strings.HasPrefix(ct, MIMEApplicationXML) {
		err = xml.NewDecoder(body).Decode(i)
	} else if strings.HasPrefix(ct, MIMEApplicationForm) {
		err = b.structMap(i, r.PostForm().All())
	} else if strings.Contains(ct, MIMEMultipartForm) {
		err = b.structMap(i, r.Form().All())
	}
	return
}

func (b *binder) Bind(i interface{}, c Context) (err error) {
	err = b.MustBind(i, c)
	if err == ErrUnsupportedMediaType {
		err = nil
	}
	return
}

// StructMap function mapping params to controller's properties
func (b *binder) structMap(m interface{}, data map[string][]string) error {
	return NamedStructMap(b.Echo, m, data, ``)
}

// SplitJSON user[name][test]
func SplitJSON(s string) ([]string, error) {
	var res []string
	var begin, end int
	var isleft bool
	for i, r := range s {
		switch r {
		case '[':
			isleft = true
			if i > 0 && s[i-1] != ']' {
				if begin == end {
					return nil, errors.New(`unknow character`)
				}
				res = append(res, s[begin:end+1])
			}
			begin = i + 1
			end = begin
		case ']':
			if !isleft {
				return nil, errors.New(`unknow character`)
			}
			isleft = false
			if begin != end {
				res = append(res, s[begin:end+1])
				begin = i + 1
				end = begin
			}
		default:
			end = i
		}
		if i == len(s)-1 && begin != end {
			res = append(res, s[begin:end+1])
		}
	}
	return res, nil
}

func NamedStructMap(e *Echo, m interface{}, data map[string][]string, topName string) error {
	vc := reflect.ValueOf(m)
	tc := reflect.TypeOf(m)

	switch tc.Kind() {
	case reflect.Struct:
	case reflect.Ptr:
		vc = vc.Elem()
		tc = tc.Elem()
	}
	var validator *validation.Validation
	for k, t := range data {

		if k == `` || k[0] == '_' {
			continue
		}

		if topName != `` {
			if !strings.HasPrefix(k, topName) {
				continue
			}
			k = k[len(topName)+1:]
		}

		v := t[0]
		names := strings.Split(k, `.`)
		var err error
		length := len(names)
		if length == 1 && strings.HasSuffix(k, `]`) {
			names, err = SplitJSON(k)
			if err != nil {
				e.Logger().Warnf(`Unrecognize form key %v %v`, k, err)
				continue
			}
			length = len(names)
		}
		value := vc
		typev := tc
		for i, name := range names {
			name = strings.Title(name)

			//不是最后一个元素
			if i != length-1 {
				if value.Kind() != reflect.Struct {
					e.Logger().Warnf(`arg error, value kind is %v`, value.Kind())
					break
				}
				value = value.FieldByName(name)
				if !value.IsValid() {
					e.Logger().Warnf(`(%v value is not valid %v)`, name, value)
					break
				}
				if !value.CanSet() {
					e.Logger().Warnf(`can not set %v -> %v`, name, value.Interface())
					break
				}
				if value.Kind() == reflect.Ptr {
					if value.IsNil() {
						value.Set(reflect.New(value.Type().Elem()))
					}
					value = value.Elem()
				}
				typev = value.Type()
				f, _ := typev.FieldByName(name)
				if tagfast.Value(tc, f, `form_options`) == `-` {
					break
				}
			} else {
				if value.Kind() != reflect.Struct {
					e.Logger().Warnf(`arg error, value %v kind is %v`, name, value.Kind())
					break
				}
				tv := value.FieldByName(name)
				if !tv.IsValid() {
					break
				}
				if !tv.CanSet() {
					e.Logger().Warnf(`can not set %v to %v`, k, tv)
					break
				}
				f, _ := typev.FieldByName(name)
				if tagfast.Value(tc, f, `form_options`) == `-` {
					break
				}
				if tv.Kind() == reflect.Ptr {
					tv.Set(reflect.New(tv.Type().Elem()))
					tv = tv.Elem()
				}

				var l interface{}
				switch k := tv.Kind(); k {
				case reflect.String:
					switch tagfast.Value(tc, f, `form_filter`) {
					case `html`:
						v = DefaultHtmlFilter(v)
					}
					l = v
					tv.Set(reflect.ValueOf(l))
				case reflect.Bool:
					l = (v != `false` && v != `0` && v != ``)
					tv.Set(reflect.ValueOf(l))
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
					dateformat := tagfast.Value(tc, f, `form_format`)
					if dateformat != `` {
						t, err := time.Parse(dateformat, v)
						if err != nil {
							e.Logger().Warnf(`arg %v as int: %v`, v, err)
							l = int(0)
						} else {
							l = int(t.Unix())
						}
					} else {
						x, err := strconv.Atoi(v)
						if err != nil {
							e.Logger().Warnf(`arg %v as int: %v`, v, err)
						}
						l = x
					}
					tv.Set(reflect.ValueOf(l))
				case reflect.Int64:
					dateformat := tagfast.Value(tc, f, `form_format`)
					if dateformat != `` {
						t, err := time.Parse(dateformat, v)
						if err != nil {
							e.Logger().Warnf(`arg %v as int64: %v`, v, err)
							l = int64(0)
						} else {
							l = t.Unix()
						}
					} else {
						x, err := strconv.ParseInt(v, 10, 64)
						if err != nil {
							e.Logger().Warnf(`arg %v as int64: %v`, v, err)
						}
						l = x
					}
					tv.Set(reflect.ValueOf(l))
				case reflect.Float32, reflect.Float64:
					x, err := strconv.ParseFloat(v, 64)
					if err != nil {
						e.Logger().Warnf(`arg %v as float64: %v`, v, err)
					}
					l = x
					tv.Set(reflect.ValueOf(l))
				case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
					dateformat := tagfast.Value(tc, f, `form_format`)
					if dateformat != `` {
						t, err := time.Parse(dateformat, v)
						if err != nil {
							e.Logger().Warnf(`arg %v as uint: %v`, v, err)
							l = uint64(0)
						} else {
							l = uint64(t.Unix())
						}
					} else {
						x, err := strconv.ParseUint(v, 10, 64)
						if err != nil {
							e.Logger().Warnf(`arg %v as uint: %v`, v, err)
						}
						l = x
					}
					tv.Set(reflect.ValueOf(l))
				case reflect.Struct:
					if tvf, ok := tv.Interface().(FromConversion); ok {
						err := tvf.FromString(v)
						if err != nil {
							e.Logger().Warnf(`struct %v invoke FromString faild`, tvf)
						}
					} else if tv.Type().String() == `time.Time` {
						x, err := time.Parse(`2006-01-02 15:04:05.000 -0700`, v)
						if err != nil {
							x, err = time.Parse(`2006-01-02 15:04:05`, v)
							if err != nil {
								x, err = time.Parse(`2006-01-02`, v)
								if err != nil {
									e.Logger().Warnf(`unsupported time format %v, %v`, v, err)
								}
							}
						}
						l = x
						tv.Set(reflect.ValueOf(l))
					} else {
						e.Logger().Warn(`can not set an struct which is not implement Fromconversion interface`)
					}
				case reflect.Ptr:
					e.Logger().Warn(`can not set an ptr of ptr`)
				case reflect.Slice, reflect.Array:
					tt := tv.Type().Elem()
					tk := tt.Kind()

					if tv.IsNil() {
						tv.Set(reflect.MakeSlice(tv.Type(), len(t), len(t)))
					}

					for i, s := range t {
						var err error
						switch tk {
						case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int8, reflect.Int64:
							var v int64
							v, err = strconv.ParseInt(s, 10, tt.Bits())
							if err == nil {
								tv.Index(i).SetInt(v)
							}
						case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
							var v uint64
							v, err = strconv.ParseUint(s, 10, tt.Bits())
							if err == nil {
								tv.Index(i).SetUint(v)
							}
						case reflect.Float32, reflect.Float64:
							var v float64
							v, err = strconv.ParseFloat(s, tt.Bits())
							if err == nil {
								tv.Index(i).SetFloat(v)
							}
						case reflect.Bool:
							var v bool
							v, err = strconv.ParseBool(s)
							if err == nil {
								tv.Index(i).SetBool(v)
							}
						case reflect.String:
							tv.Index(i).SetString(s)
						case reflect.Complex64, reflect.Complex128:
							// TODO:
							err = fmt.Errorf(`unsupported slice element type %v`, tk.String())
						default:
							err = fmt.Errorf(`unsupported slice element type %v`, tk.String())
						}
						if err != nil {
							e.Logger().Warnf(`slice error: %v, %v`, name, err)
						}
					}
				default:
					break
				}
				valid := tagfast.Value(tc, f, `valid`)
				if len(valid) > 0 {
					if validator == nil {
						validator = validation.New()
					}
					ok, err := validator.ValidSimple(name, fmt.Sprintf(`%v`, l), valid)
					if !ok {
						return validator.Errors[0].WithField()
					}
					if err != nil {
						e.Logger().Warn(err)
					}
				}
			}
		}
	}
	return nil
}

// FromConversion a struct implements this interface can be convert from request param to a struct
type FromConversion interface {
	FromString(content string) error
}

// ToConversion a struct implements this interface can be convert from struct to template variable
// Not Implemented
type ToConversion interface {
	ToString() string
}

var (
	DefaultFieldNameFormatter = func(topName, fieldName string) string {
		var fName string
		if len(topName) == 0 {
			fName = fieldName
		} else {
			fName = topName + "." + fieldName
		}
		return fName
	}
	LowerCaseFirstFieldNameFormatter = func(topName, fieldName string) string {
		var fName string
		s := []rune(fieldName)
		if len(s) > 0 {
			s[0] = unicode.ToLower(s[0])
			fieldName = string(s)
		}
		if len(topName) == 0 {
			fName = fieldName
		} else {
			fName = topName + "." + fieldName
		}
		return fName
	}
)

func StructToForm(ctx Context, m interface{}, topName string, fieldNameFormatter func(string, string) string) {
	vc := reflect.ValueOf(m)
	tc := reflect.TypeOf(m)

	switch tc.Kind() {
	case reflect.Struct:
	case reflect.Ptr:
		vc = vc.Elem()
		tc = tc.Elem()
	}
	l := tc.NumField()
	f := ctx.Request().Form()
	if fieldNameFormatter == nil {
		fieldNameFormatter = DefaultFieldNameFormatter
	}

	for i := 0; i < l; i++ {
		fVal := vc.Field(i)
		fTyp := tc.Field(i)

		fName := fieldNameFormatter(topName, fTyp.Name)
		switch fTyp.Type.String() {
		case "time.Time":
			if t, y := fVal.Interface().(time.Time); y {
				dateformat := tagfast.Value(tc, fTyp, `form_format`)
				if dateformat != `` {
					f.Add(fName, t.Format(dateformat))
				} else {
					f.Add(fName, t.Format(`2006-01-02 15:04:05`))
				}
			}
		case "struct":
			StructToForm(ctx, fVal.Interface(), fName, fieldNameFormatter)
		default:
			f.Add(fName, fmt.Sprint(fVal.Interface()))
		}
	}
}
<commit_msg>update<commit_after>package echo

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"
	"unicode"

	"github.com/webx-top/tagfast"
	"github.com/webx-top/validation"
)

var DefaultHtmlFilter = func(v string) (r string) {
	return v
}

type (
	// Binder is the interface that wraps the Bind method.
	Binder interface {
		Bind(interface{}, Context) error
		MustBind(interface{}, Context) error
	}
	binder struct {
		*Echo
	}
)

func (b *binder) MustBind(i interface{}, c Context) (err error) {
	r := c.Request()
	body := r.Body()
	if body == nil {
		err = NewHTTPError(http.StatusBadRequest, "Request body can't be nil")
		return
	}
	defer body.Close()
	ct := r.Header().Get(HeaderContentType)
	err = ErrUnsupportedMediaType
	if strings.HasPrefix(ct, MIMEApplicationJSON) {
		err = json.NewDecoder(body).Decode(i)
	} else if strings.HasPrefix(ct, MIMEApplicationXML) {
		err = xml.NewDecoder(body).Decode(i)
	} else if strings.HasPrefix(ct, MIMEApplicationForm) {
		err = b.structMap(i, r.PostForm().All())
	} else if strings.Contains(ct, MIMEMultipartForm) {
		err = b.structMap(i, r.Form().All())
	}
	return
}

func (b *binder) Bind(i interface{}, c Context) (err error) {
	err = b.MustBind(i, c)
	if err == ErrUnsupportedMediaType {
		err = nil
	}
	return
}

// StructMap function mapping params to controller's properties
func (b *binder) structMap(m interface{}, data map[string][]string) error {
	return NamedStructMap(b.Echo, m, data, ``)
}

// SplitJSON user[name][test]
func SplitJSON(s string) ([]string, error) {
	var res []string
	var begin, end int
	var isleft bool
	for i, r := range s {
		switch r {
		case '[':
			isleft = true
			if i > 0 && s[i-1] != ']' {
				if begin == end {
					return nil, errors.New(`unknow character`)
				}
				res = append(res, s[begin:end+1])
			}
			begin = i + 1
			end = begin
		case ']':
			if !isleft {
				return nil, errors.New(`unknow character`)
			}
			isleft = false
			if begin != end {
				res = append(res, s[begin:end+1])
				begin = i + 1
				end = begin
			}
		default:
			end = i
		}
		if i == len(s)-1 && begin != end {
			res = append(res, s[begin:end+1])
		}
	}
	return res, nil
}

func NamedStructMap(e *Echo, m interface{}, data map[string][]string, topName string) error {
	vc := reflect.ValueOf(m)
	tc := reflect.TypeOf(m)

	switch tc.Kind() {
	case reflect.Struct:
	case reflect.Ptr:
		vc = vc.Elem()
		tc = tc.Elem()
	}
	var validator *validation.Validation
	for k, t := range data {

		if k == `` || k[0] == '_' {
			continue
		}

		if topName != `` {
			if !strings.HasPrefix(k, topName) {
				continue
			}
			k = k[len(topName)+1:]
		}

		v := t[0]
		names := strings.Split(k, `.`)
		var err error
		length := len(names)
		if length == 1 && strings.HasSuffix(k, `]`) {
			names, err = SplitJSON(k)
			if err != nil {
				e.Logger().Warnf(`Unrecognize form key %v %v`, k, err)
				continue
			}
			length = len(names)
		}
		value := vc
		typev := tc
		for i, name := range names {
			name = strings.Title(name)

			//不是最后一个元素
			if i != length-1 {
				if value.Kind() != reflect.Struct {
					e.Logger().Warnf(`arg error, value kind is %v`, value.Kind())
					break
				}
				value = value.FieldByName(name)
				if !value.IsValid() {
					e.Logger().Warnf(`(%v value is not valid %v)`, name, value)
					break
				}
				if !value.CanSet() {
					e.Logger().Warnf(`can not set %v -> %v`, name, value.Interface())
					break
				}
				if value.Kind() == reflect.Ptr {
					if value.IsNil() {
						value.Set(reflect.New(value.Type().Elem()))
					}
					value = value.Elem()
				}
				typev = value.Type()
				f, _ := typev.FieldByName(name)
				if tagfast.Value(tc, f, `form_options`) == `-` {
					break
				}
			} else {
				if value.Kind() != reflect.Struct {
					e.Logger().Warnf(`arg error, value %v kind is %v`, name, value.Kind())
					break
				}
				tv := value.FieldByName(name)
				if !tv.IsValid() {
					break
				}
				if !tv.CanSet() {
					e.Logger().Warnf(`can not set %v to %v`, k, tv)
					break
				}
				f, _ := typev.FieldByName(name)
				if tagfast.Value(tc, f, `form_options`) == `-` {
					break
				}
				if tv.Kind() == reflect.Ptr {
					tv.Set(reflect.New(tv.Type().Elem()))
					tv = tv.Elem()
				}

				var l interface{}
				switch k := tv.Kind(); k {
				case reflect.String:
					switch tagfast.Value(tc, f, `form_filter`) {
					case `html`:
						v = DefaultHtmlFilter(v)
					}
					l = v
					tv.Set(reflect.ValueOf(l))
				case reflect.Bool:
					l = (v != `false` && v != `0` && v != ``)
					tv.Set(reflect.ValueOf(l))
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
					dateformat := tagfast.Value(tc, f, `form_format`)
					if dateformat != `` {
						t, err := time.Parse(dateformat, v)
						if err != nil {
							e.Logger().Warnf(`arg %v as int: %v`, v, err)
							l = int(0)
						} else {
							l = int(t.Unix())
						}
					} else {
						x, err := strconv.Atoi(v)
						if err != nil {
							e.Logger().Warnf(`arg %v as int: %v`, v, err)
						}
						l = x
					}
					tv.Set(reflect.ValueOf(l))
				case reflect.Int64:
					dateformat := tagfast.Value(tc, f, `form_format`)
					if dateformat != `` {
						t, err := time.Parse(dateformat, v)
						if err != nil {
							e.Logger().Warnf(`arg %v as int64: %v`, v, err)
							l = int64(0)
						} else {
							l = t.Unix()
						}
					} else {
						x, err := strconv.ParseInt(v, 10, 64)
						if err != nil {
							e.Logger().Warnf(`arg %v as int64: %v`, v, err)
						}
						l = x
					}
					tv.Set(reflect.ValueOf(l))
				case reflect.Float32, reflect.Float64:
					x, err := strconv.ParseFloat(v, 64)
					if err != nil {
						e.Logger().Warnf(`arg %v as float64: %v`, v, err)
					}
					l = x
					tv.Set(reflect.ValueOf(l))
				case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
					dateformat := tagfast.Value(tc, f, `form_format`)
					if dateformat != `` {
						t, err := time.Parse(dateformat, v)
						if err != nil {
							e.Logger().Warnf(`arg %v as uint: %v`, v, err)
							l = uint64(0)
						} else {
							l = uint64(t.Unix())
						}
					} else {
						x, err := strconv.ParseUint(v, 10, 64)
						if err != nil {
							e.Logger().Warnf(`arg %v as uint: %v`, v, err)
						}
						l = x
					}
					tv.Set(reflect.ValueOf(l))
				case reflect.Struct:
					if tvf, ok := tv.Interface().(FromConversion); ok {
						err := tvf.FromString(v)
						if err != nil {
							e.Logger().Warnf(`struct %v invoke FromString faild`, tvf)
						}
					} else if tv.Type().String() == `time.Time` {
						x, err := time.Parse(`2006-01-02 15:04:05.000 -0700`, v)
						if err != nil {
							x, err = time.Parse(`2006-01-02 15:04:05`, v)
							if err != nil {
								x, err = time.Parse(`2006-01-02`, v)
								if err != nil {
									e.Logger().Warnf(`unsupported time format %v, %v`, v, err)
								}
							}
						}
						l = x
						tv.Set(reflect.ValueOf(l))
					} else {
						e.Logger().Warn(`can not set an struct which is not implement Fromconversion interface`)
					}
				case reflect.Ptr:
					e.Logger().Warn(`can not set an ptr of ptr`)
				case reflect.Slice, reflect.Array:
					tt := tv.Type().Elem()
					tk := tt.Kind()

					if tv.IsNil() {
						tv.Set(reflect.MakeSlice(tv.Type(), len(t), len(t)))
					}

					for i, s := range t {
						var err error
						switch tk {
						case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int8, reflect.Int64:
							var v int64
							v, err = strconv.ParseInt(s, 10, tt.Bits())
							if err == nil {
								tv.Index(i).SetInt(v)
							}
						case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
							var v uint64
							v, err = strconv.ParseUint(s, 10, tt.Bits())
							if err == nil {
								tv.Index(i).SetUint(v)
							}
						case reflect.Float32, reflect.Float64:
							var v float64
							v, err = strconv.ParseFloat(s, tt.Bits())
							if err == nil {
								tv.Index(i).SetFloat(v)
							}
						case reflect.Bool:
							var v bool
							v, err = strconv.ParseBool(s)
							if err == nil {
								tv.Index(i).SetBool(v)
							}
						case reflect.String:
							tv.Index(i).SetString(s)
						case reflect.Complex64, reflect.Complex128:
							// TODO:
							err = fmt.Errorf(`unsupported slice element type %v`, tk.String())
						default:
							err = fmt.Errorf(`unsupported slice element type %v`, tk.String())
						}
						if err != nil {
							e.Logger().Warnf(`slice error: %v, %v`, name, err)
						}
					}
				default:
					break
				}
				valid := tagfast.Value(tc, f, `valid`)
				if len(valid) > 0 {
					if validator == nil {
						validator = validation.New()
					}
					ok, err := validator.ValidSimple(name, fmt.Sprintf(`%v`, l), valid)
					if !ok {
						return validator.Errors[0].WithField()
					}
					if err != nil {
						e.Logger().Warn(err)
					}
				}
			}
		}
	}
	return nil
}

// FromConversion a struct implements this interface can be convert from request param to a struct
type FromConversion interface {
	FromString(content string) error
}

// ToConversion a struct implements this interface can be convert from struct to template variable
// Not Implemented
type ToConversion interface {
	ToString() string
}

var (
	DefaultFieldNameFormatter = func(topName, fieldName string) string {
		var fName string
		if len(topName) == 0 {
			fName = fieldName
		} else {
			fName = topName + "." + fieldName
		}
		return fName
	}
	LowerCaseFirstFieldNameFormatter = func(topName, fieldName string) string {
		var fName string
		s := []rune(fieldName)
		if len(s) > 0 {
			s[0] = unicode.ToLower(s[0])
			fieldName = string(s)
		}
		if len(topName) == 0 {
			fName = fieldName
		} else {
			fName = topName + "." + fieldName
		}
		return fName
	}
)

func StructToForm(ctx Context, m interface{}, topName string, fieldNameFormatter func(string, string) string) {
	vc := reflect.ValueOf(m)
	tc := reflect.TypeOf(m)

	switch tc.Kind() {
	case reflect.Struct:
	case reflect.Ptr:
		vc = vc.Elem()
		tc = tc.Elem()
	}
	l := tc.NumField()
	f := ctx.Request().Form()
	if fieldNameFormatter == nil {
		fieldNameFormatter = DefaultFieldNameFormatter
	}

	for i := 0; i < l; i++ {
		fVal := vc.Field(i)
		fTyp := tc.Field(i)

		fName := fieldNameFormatter(topName, fTyp.Name)
		if !fVal.CanInterface() {
			continue
		}
		switch fTyp.Type.String() {
		case "time.Time":
			if t, y := fVal.Interface().(time.Time); y {
				dateformat := tagfast.Value(tc, fTyp, `form_format`)
				if dateformat != `` {
					f.Add(fName, t.Format(dateformat))
				} else {
					f.Add(fName, t.Format(`2006-01-02 15:04:05`))
				}
			}
		case "struct":
			StructToForm(ctx, fVal.Interface(), fName, fieldNameFormatter)
		default:
			f.Add(fName, fmt.Sprint(fVal.Interface()))
		}
	}
}
<|endoftext|>


<commit_before>package echo

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"net/http"
	"reflect"
	"strconv"
	"strings"
)

type (
	// Binder is the interface that wraps the Bind method.
	Binder interface {
		Bind(interface{}, Context) error
	}

	binder struct{}
)

func (b *binder) Bind(i interface{}, c Context) (err error) {
	req := c.Request()
	if req.Method() == GET {
		if err = b.bindData(i, c.QueryParams()); err != nil {
			err = NewHTTPError(http.StatusBadRequest, err.Error())
		}
		return
	}
	ctype := req.Header().Get(HeaderContentType)
	if req.Body() == nil {
		err = NewHTTPError(http.StatusBadRequest, "request body can't be empty")
		return
	}
	err = ErrUnsupportedMediaType
	switch {
	case strings.HasPrefix(ctype, MIMEApplicationJSON):
		if err = json.NewDecoder(req.Body()).Decode(i); err != nil {
			err = NewHTTPError(http.StatusBadRequest, err.Error())
		}
	case strings.HasPrefix(ctype, MIMEApplicationXML):
		if err = xml.NewDecoder(req.Body()).Decode(i); err != nil {
			err = NewHTTPError(http.StatusBadRequest, err.Error())
		}
	case strings.HasPrefix(ctype, MIMEApplicationForm), strings.HasPrefix(ctype, MIMEMultipartForm):
		if err = b.bindData(i, req.FormParams()); err != nil {
			err = NewHTTPError(http.StatusBadRequest, err.Error())
		}
	}
	return
}

func (b *binder) bindData(ptr interface{}, data map[string][]string) error {
	typ := reflect.TypeOf(ptr).Elem()
	val := reflect.ValueOf(ptr).Elem()

	if typ.Kind() != reflect.Struct {
		return errors.New("binding element must be a struct")
	}

	for i := 0; i < typ.NumField(); i++ {
		typeField := typ.Field(i)
		structField := val.Field(i)
		if !structField.CanSet() {
			continue
		}
		structFieldKind := structField.Kind()
		inputFieldName := typeField.Tag.Get("form")

		if inputFieldName == "" {
			inputFieldName = typeField.Name
			// If "form" tag is nil, we inspect if the field is a struct.
			if structFieldKind == reflect.Struct {
				err := b.bindData(structField.Addr().Interface(), data)
				if err != nil {
					return err
				}
				continue
			}
		}
		inputValue, exists := data[inputFieldName]
		if !exists {
			continue
		}

		numElems := len(inputValue)
		if structFieldKind == reflect.Slice && numElems > 0 {
			sliceOf := structField.Type().Elem().Kind()
			slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
			for i := 0; i < numElems; i++ {
				if err := setWithProperType(sliceOf, inputValue[i], slice.Index(i)); err != nil {
					return err
				}
			}
			val.Field(i).Set(slice)
		} else {
			if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil {
				return err
			}
		}
	}
	return nil
}

func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
	switch valueKind {
	case reflect.Int:
		return setIntField(val, 0, structField)
	case reflect.Int8:
		return setIntField(val, 8, structField)
	case reflect.Int16:
		return setIntField(val, 16, structField)
	case reflect.Int32:
		return setIntField(val, 32, structField)
	case reflect.Int64:
		return setIntField(val, 64, structField)
	case reflect.Uint:
		return setUintField(val, 0, structField)
	case reflect.Uint8:
		return setUintField(val, 8, structField)
	case reflect.Uint16:
		return setUintField(val, 16, structField)
	case reflect.Uint32:
		return setUintField(val, 32, structField)
	case reflect.Uint64:
		return setUintField(val, 64, structField)
	case reflect.Bool:
		return setBoolField(val, structField)
	case reflect.Float32:
		return setFloatField(val, 32, structField)
	case reflect.Float64:
		return setFloatField(val, 64, structField)
	case reflect.String:
		structField.SetString(val)
	default:
		return errors.New("unknown type")
	}
	return nil
}

func setIntField(value string, bitSize int, field reflect.Value) error {
	if value == "" {
		value = "0"
	}
	intVal, err := strconv.ParseInt(value, 10, bitSize)
	if err == nil {
		field.SetInt(intVal)
	}
	return err
}

func setUintField(value string, bitSize int, field reflect.Value) error {
	if value == "" {
		value = "0"
	}
	uintVal, err := strconv.ParseUint(value, 10, bitSize)
	if err == nil {
		field.SetUint(uintVal)
	}
	return err
}

func setBoolField(value string, field reflect.Value) error {
	if value == "" {
		value = "false"
	}
	boolVal, err := strconv.ParseBool(value)
	if err == nil {
		field.SetBool(boolVal)
	}
	return err
}

func setFloatField(value string, bitSize int, field reflect.Value) error {
	if value == "" {
		value = "0.0"
	}
	floatVal, err := strconv.ParseFloat(value, bitSize)
	if err == nil {
		field.SetFloat(floatVal)
	}
	return err
}
<commit_msg>Closes #610, Closes #611<commit_after>package echo

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"net/http"
	"reflect"
	"strconv"
	"strings"
)

type (
	// Binder is the interface that wraps the Bind method.
	Binder interface {
		Bind(interface{}, Context) error
	}

	binder struct{}
)

func (b *binder) Bind(i interface{}, c Context) (err error) {
	req := c.Request()
	if req.Method() == GET {
		if err = b.bindData(i, c.QueryParams()); err != nil {
			err = NewHTTPError(http.StatusBadRequest, err.Error())
		}
		return
	}
	ctype := req.Header().Get(HeaderContentType)
	if req.Body() == nil {
		err = NewHTTPError(http.StatusBadRequest, "request body can't be empty")
		return
	}
	err = ErrUnsupportedMediaType
	switch {
	case strings.HasPrefix(ctype, MIMEApplicationJSON):
		if err = json.NewDecoder(req.Body()).Decode(i); err != nil {
			if ute, ok := err.(*json.UnmarshalTypeError); ok {
				err = NewHTTPError(http.StatusBadRequest, fmt.Sprintf("unmarshal type error: expected=%v, got=%v, offset=%v", ute.Type, ute.Value, ute.Offset))
			} else if se, ok := err.(*json.SyntaxError); ok {
				err = NewHTTPError(http.StatusBadRequest, fmt.Sprintf("syntax error: offset=%v, error=%v", se.Offset, se.Error()))
			} else {
				err = NewHTTPError(http.StatusBadRequest, err.Error())
			}
		}
	case strings.HasPrefix(ctype, MIMEApplicationXML):
		if err = xml.NewDecoder(req.Body()).Decode(i); err != nil {
			if ute, ok := err.(*xml.UnsupportedTypeError); ok {
				err = NewHTTPError(http.StatusBadRequest, fmt.Sprintf("unsupported type error: type=%v, error=%v", ute.Type, ute.Error()))
			} else if se, ok := err.(*xml.SyntaxError); ok {
				err = NewHTTPError(http.StatusBadRequest, fmt.Sprintf("syntax error: line=%v, error=%v", se.Line, se.Error()))
			} else {
				err = NewHTTPError(http.StatusBadRequest, err.Error())
			}
		}
	case strings.HasPrefix(ctype, MIMEApplicationForm), strings.HasPrefix(ctype, MIMEMultipartForm):
		if err = b.bindData(i, req.FormParams()); err != nil {
			err = NewHTTPError(http.StatusBadRequest, err.Error())
		}
	}
	return
}

func (b *binder) bindData(ptr interface{}, data map[string][]string) error {
	typ := reflect.TypeOf(ptr).Elem()
	val := reflect.ValueOf(ptr).Elem()

	if typ.Kind() != reflect.Struct {
		return errors.New("binding element must be a struct")
	}

	for i := 0; i < typ.NumField(); i++ {
		typeField := typ.Field(i)
		structField := val.Field(i)
		if !structField.CanSet() {
			continue
		}
		structFieldKind := structField.Kind()
		inputFieldName := typeField.Tag.Get("form")

		if inputFieldName == "" {
			inputFieldName = typeField.Name
			// If "form" tag is nil, we inspect if the field is a struct.
			if structFieldKind == reflect.Struct {
				err := b.bindData(structField.Addr().Interface(), data)
				if err != nil {
					return err
				}
				continue
			}
		}
		inputValue, exists := data[inputFieldName]
		if !exists {
			continue
		}

		numElems := len(inputValue)
		if structFieldKind == reflect.Slice && numElems > 0 {
			sliceOf := structField.Type().Elem().Kind()
			slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
			for i := 0; i < numElems; i++ {
				if err := setWithProperType(sliceOf, inputValue[i], slice.Index(i)); err != nil {
					return err
				}
			}
			val.Field(i).Set(slice)
		} else {
			if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil {
				return err
			}
		}
	}
	return nil
}

func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
	switch valueKind {
	case reflect.Int:
		return setIntField(val, 0, structField)
	case reflect.Int8:
		return setIntField(val, 8, structField)
	case reflect.Int16:
		return setIntField(val, 16, structField)
	case reflect.Int32:
		return setIntField(val, 32, structField)
	case reflect.Int64:
		return setIntField(val, 64, structField)
	case reflect.Uint:
		return setUintField(val, 0, structField)
	case reflect.Uint8:
		return setUintField(val, 8, structField)
	case reflect.Uint16:
		return setUintField(val, 16, structField)
	case reflect.Uint32:
		return setUintField(val, 32, structField)
	case reflect.Uint64:
		return setUintField(val, 64, structField)
	case reflect.Bool:
		return setBoolField(val, structField)
	case reflect.Float32:
		return setFloatField(val, 32, structField)
	case reflect.Float64:
		return setFloatField(val, 64, structField)
	case reflect.String:
		structField.SetString(val)
	default:
		return errors.New("unknown type")
	}
	return nil
}

func setIntField(value string, bitSize int, field reflect.Value) error {
	if value == "" {
		value = "0"
	}
	intVal, err := strconv.ParseInt(value, 10, bitSize)
	if err == nil {
		field.SetInt(intVal)
	}
	return err
}

func setUintField(value string, bitSize int, field reflect.Value) error {
	if value == "" {
		value = "0"
	}
	uintVal, err := strconv.ParseUint(value, 10, bitSize)
	if err == nil {
		field.SetUint(uintVal)
	}
	return err
}

func setBoolField(value string, field reflect.Value) error {
	if value == "" {
		value = "false"
	}
	boolVal, err := strconv.ParseBool(value)
	if err == nil {
		field.SetBool(boolVal)
	}
	return err
}

func setFloatField(value string, bitSize int, field reflect.Value) error {
	if value == "" {
		value = "0.0"
	}
	floatVal, err := strconv.ParseFloat(value, bitSize)
	if err == nil {
		field.SetFloat(floatVal)
	}
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"math"
	"sync"
	"time"
)

const (
	maxEnergyGain = 5
	maxEnergyLoss = 5
	maxLifeLoss   = 5
)

func (game *GameInfo) runEngine(wg *sync.WaitGroup) {
	wg.Add(len(game.Teams))
	for i := range game.Teams {
		go game.handleTeam(&game.Teams[i], wg)
	}
}

func (game *GameInfo) handleTeam(team *Team, wg *sync.WaitGroup) {
	var temperatureRatio float64
	var radiationRatio float64
	var energyGain float64
	var energyLoss float64
	var lifeLoss float64

	for team.Life > 0 && game.Running {
		time.Sleep(1 * time.Second)

		if team.Energy <= 0 {
			team.Shield = false
		}

		if team.Shield {
			radiationRatio = (float64)(game.Reading.Radiation-minRadiation) / (float64)(maxRadiation-minRadiation)
			energyLoss = radiationRatio * maxEnergyLoss
			team.Energy = int64(math.Max(float64(team.Energy)-math.Ceil(energyLoss), 0))
			log.Printf("Team %s: Energy -%.2f\n", team.Name, energyLoss)
			continue
		}

		radiationRatio = (float64)(game.Reading.Radiation-minRadiation) / (float64)(maxRadiation-minRadiation)
		lifeLoss = radiationRatio * maxLifeLoss
		team.Life = int64(math.Max(float64(team.Life)-math.Ceil(lifeLoss), 0))

		temperatureRatio = (game.Reading.Temperature - minTemperature) / (maxTemperature - minTemperature)
		energyGain = temperatureRatio * maxEnergyGain
		team.Energy = int64(math.Min(float64(team.Energy)+math.Ceil(energyGain), 100))

		log.Printf("Team %s: Life -%.2f, Energy +%.2f\n", team.Name, lifeLoss, energyGain)
	}

	log.Println("Exiting goroutine for team", team.Name)
	wg.Done()
}
<commit_msg>the '0 shield bias' fix<commit_after>package main

import (
	"log"
	"math"
	"sync"
	"time"
)

const (
	maxEnergyGain = 5
	maxEnergyLoss = 5
	maxLifeLoss   = 5
)

func (game *GameInfo) runEngine(wg *sync.WaitGroup) {
	wg.Add(len(game.Teams))
	for i := range game.Teams {
		go game.handleTeam(&game.Teams[i], wg)
	}
}

func (game *GameInfo) handleTeam(team *Team, wg *sync.WaitGroup) {
	var temperatureRatio float64
	var radiationRatio float64
	var energyGain float64
	var energyLoss float64
	var lifeLoss float64

	for team.Life > 0 && game.Running {
		time.Sleep(1 * time.Second)
		radiationRatio = (float64)(game.Reading.Radiation-minRadiation) / (float64)(maxRadiation-minRadiation)
		energyLoss = radiationRatio * maxEnergyLoss
		if team.Energy-energyloss <= 0 {
			team.Shield = false
		}

		if team.Shield {
			team.Energy = int64(math.Max(float64(team.Energy)-math.Ceil(energyLoss), 0))
			log.Printf("Team %s: Energy -%.2f\n", team.Name, energyLoss)
			continue
		}

		radiationRatio = (float64)(game.Reading.Radiation-minRadiation) / (float64)(maxRadiation-minRadiation)
		lifeLoss = radiationRatio * maxLifeLoss
		team.Life = int64(math.Max(float64(team.Life)-math.Ceil(lifeLoss), 0))

		temperatureRatio = (game.Reading.Temperature - minTemperature) / (maxTemperature - minTemperature)
		energyGain = temperatureRatio * maxEnergyGain
		team.Energy = int64(math.Min(float64(team.Energy)+math.Ceil(energyGain), 100))

		log.Printf("Team %s: Life -%.2f, Energy +%.2f\n", team.Name, lifeLoss, energyGain)
	}

	log.Println("Exiting goroutine for team", team.Name)
	wg.Done()
}
<|endoftext|>


<commit_before>package main

import (

	"database/sql"
	"strconv"
	log "github.com/Sirupsen/logrus"
)

func Insert_World_Event_for_Hero(heroID int64, worldEvent string, conn *sql.DB) {

	log.Info("Inserting World Event: HeroID: " + strconv.FormatInt(heroID, 10) + " | Event: " + worldEvent)

	var query = "INSERT INTO worldevent (event_text) VALUES ('" + worldEvent + "')"

	log.Info("World Event Query: " + query)

	statement, err := conn.Exec(query)

	last_worldevent_Id, err := statement.LastInsertId()

	if err != nil {
		log.Errorln("DB: Insert_Item_for_Hero: Worldevent Insert failed: %s", err)
	}

	if last_worldevent_Id != 0 {

		Insert_Hero_World_Event(heroID, int(last_worldevent_Id), conn)
	}
}

func Insert_Hero_World_Event(heroID int64, woldEvent_id int, conn *sql.DB) {

	var query = "INSERT INTO heroworldevent (hero_id, worldevent_id ) VALUES (" + strconv.FormatInt(heroID, 10) + ", " + strconv.Itoa(woldEvent_id) + ")"

	log.Info("Heroworldevent Query: " + query)

	_, err := conn.Exec(query)

	if err != nil {
		log.Errorln("DB: Insert_Item_for_Hero: Heroworldevent Insert failed: %s", err)
	}
}
<commit_msg>Updated functions documentation and logging information<commit_after>package main

import (

	"database/sql"
	"strconv"
	log "github.com/Sirupsen/logrus"
)

//Insert World Event for Hero, adds a world event notification for a specific hero
//Parameters: Hero ID, World Event Message and the SQL.DB connection.
//Return: None
func Insert_World_Event_for_Hero(heroID int64, worldEvent string, conn *sql.DB) {

	log.Info("Inserting World Event: HeroID: " + strconv.FormatInt(heroID, 10) + " | Event: " + worldEvent)

	var query = "INSERT INTO worldevent (event_text) VALUES ('" + worldEvent + "')"

	log.Info("[DAL] World Event Query: " + query)

	statement, err := conn.Exec(query)

	last_worldevent_Id, err := statement.LastInsertId()

	if err != nil {
		log.Errorln("[DAL] Insert_Item_for_Hero: Worldevent Insert failed: %s", err)
	}

	if last_worldevent_Id != 0 {

		Insert_Hero_World_Event(heroID, int(last_worldevent_Id), conn)
	}
}

//Insert Hero World Event, populates the table that maps Heros with their World events
//Parameters: Hero ID, World Event ID and the SQL.DB connection.
//Return: None
func Insert_Hero_World_Event(heroID int64, woldEvent_id int, conn *sql.DB) {

	var query = "INSERT INTO heroworldevent (hero_id, worldevent_id ) VALUES (" + strconv.FormatInt(heroID, 10) + ", " + strconv.Itoa(woldEvent_id) + ")"

	log.Info("[DAL] Heroworldevent Query: " + query)

	_, err := conn.Exec(query)

	if err != nil {
		log.Errorln("[DAL] Insert_Item_for_Hero: Heroworldevent Insert failed: %s", err)
	}
}
<|endoftext|>


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

package bitset

import (
	"bytes"
	"fmt"
	"math"
)

const (
	lWord     uint32 = 32
	lLog2Word uint32 = 5
	allBits   uint32 = 0xffffffff
)

func wordsNeeded(n uint32) uint32 {
	if n == 0 {
		return 1
	} else if n == math.MaxUint32 {
		return math.MaxUint32 >> lLog2Word
	}
	return (n + (lWord - 1)) >> lLog2Word
}

type Bitset struct {
	n uint32
	b []uint32
}

// Returns the current size of the bitset.
func (b *Bitset) Len() uint32 {
	return b.n
}

/// Test whether bit n is set.
func (b *Bitset) Test(i uint32) bool {
	if i >= b.n {
		return false
	}
	return ((b.b[i>>lLog2Word] & (1 << (i & (lWord - 1)))) != 0)
}

// Set bit i to 1.
func (b *Bitset) Set(i uint32) {
	if i >= b.n {
		nsize := wordsNeeded(i + 1)
		l := uint32(len(b.b))
		if nsize > l {
			nb := make([]uint32, nsize-l)
			b.b = append(b.b, nb...)
		}
		b.n = i+1
	}
	b.b[i>>lLog2Word] |= (1 << (i & (lWord - 1)))
}

// Set bit i to 0.
func (b *Bitset) Clear(i uint32) {
	if i >= b.n {
		return
	}
	b.b[i>>lLog2Word] &^= 1 << (i & (lWord - 1))
}

// Flip bit i.
func (b *Bitset) Flip(i uint32) {
	if i >= b.n {
		b.Set(i)
	}
	b.b[i>>lLog2Word] ^= 1 << (i & (lWord - 1))
}

// Clear all bits in the bitset.
func (b *Bitset) ClearAll() {
	if b != nil {
		for i := range b.b {
			b.b[i] = 0
		}
	}
}

// Get the number of words used in the bitset.
func (b *Bitset) wordCount() uint32 {
	return wordsNeeded(b.n)
}

// Clone the bitset.
func (b *Bitset) Clone() *Bitset {
	c := New(b.n)
	copy(c.b, b.b)
	return c
}

// Copy the bitset into another bitset, returning the size of the destination
// bitset.
func (b *Bitset) Copy(c *Bitset) (n uint32) {
	if c == nil {
		return
	}
	copy(c.b, b.b)
	n = c.n
	if b.n < c.n {
		n = b.n
	}
	return
}

// http://en.wikipedia.org/wiki/Hamming_weight
const (
	m1 uint32 = 0x55555555 // 0101...
	m2 uint32 = 0x33333333 // 00110011...
	m4 uint32 = 0x0f0f0f0f // 00001111...
)

func popCountUint32(x uint32) uint32 {
	x -= (x >> 1) & m1             // put count of each 2 bits into those 2 bits
	x = (x & m2) + ((x >> 2) & m2) // put count of each 4 bits into those 4 bits
	x = (x + (x >> 4)) & m4        // put count of each 8 bits into those 8 bits
	x += x >> 8                    // put count of each 16 bits into their lowest 8 bits
	x += x >> 16                   // put count of each 32 bits into their lowest 8 bits
	return x & 0x7f
}

// Get the number of set bits in the bitset.
func (b *Bitset) Count() uint32 {
	if b != nil {
		sum := uint32(0)
		for _, w := range b.b {
			sum += popCountUint32(w)
		}
		return sum
	}
	return 0
}

// Test if two bitsets are equal. Returns true if both bitsets are the same
// size, and if all of the same bits are set in both bitsets.
func (b *Bitset) Equal(c *Bitset) bool {
	if c == nil {
		return false
	}
	if b.n != c.n {
		return false
	}
	for p, v := range b.b {
		if c.b[p] != v {
			return false
		}
	}
	return true
}

// Bitset &^ (and or); difference between receiver and another set.
func (b *Bitset) Difference(ob *Bitset) (result *Bitset) {
	result = b.Clone() // clone b (in case b is bigger than ob)
	szl := ob.wordCount()
	l := uint32(len(b.b))
	for i := uint32(0); i < l; i++ {
		if i >= szl {
			break
		}
		result.b[i] = b.b[i] &^ ob.b[i]
	}
	return
}

func sortByLength(a *Bitset, b *Bitset) (ap *Bitset, bp *Bitset) {
	if a.n <= b.n {
		ap, bp = a, b
	} else {
		ap, bp = b, a
	}
	return
}

// Bitset & (and); intersection of receiver and another set
func (b *Bitset) Intersection(ob *Bitset) (result *Bitset) {
	b, ob = sortByLength(b, ob)
	result = New(b.n)
	for i, w := range b.b {
		result.b[i] = w & ob.b[i]
	}
	return
}

// Bitset | (or); union of receiver and another set
func (b *Bitset) Union(ob *Bitset) (result *Bitset) {
	b, ob = sortByLength(b, ob)
	result = ob.Clone()
	szl := ob.wordCount()
	l := uint32(len(b.b))
	for i := uint32(0); i < l; i++ {
		if i >= szl {
			break
		}
		result.b[i] = b.b[i] | ob.b[i]
	}
	return
}

// Bitset ^ (xor); symmetric difference of receiver and another set.
func (b *Bitset) SymmetricDifference(ob *Bitset) (result *Bitset) {
	b, ob = sortByLength(b, ob)
	// ob is bigger, so clone it
	result = ob.Clone()
	szl := b.wordCount()
	l := uint32(len(b.b))
	for i := uint32(0); i < l; i++ {
		if i >= szl {
			break
		}
		result.b[i] = b.b[i] ^ ob.b[i]
	}
	return
}

// Return true if the bitset's length is a multiple of the word size.
func (b *Bitset) isEven() bool {
	return (b.n % lWord) == 0
}

// Clean last word by setting unused bits to 0.
func (b *Bitset) cleanLastWord() {
	if !b.isEven() {
		b.b[wordsNeeded(b.n)-1] &= (allBits >> (lWord - (b.n % lWord)))
	}
}

// Return the (local) complement of a bitset (up to n bits)
func (b *Bitset) Complement() (result *Bitset) {
	b.String()
	result = New(b.n)
	for i, w := range b.b {
		result.b[i] = ^(w)
	}
	result.cleanLastWord()
	return
}

// Returns true if all bits in the bitset are set.
func (b *Bitset) All() bool {
	return b.Count() == b.n
}

// Returns true if no bit in the bitset is set.
func (b *Bitset) None() bool {
	if b != nil {
		for _, w := range b.b {
			if w > 0 {
				return false
			}
		}
		return true
	}
	return true
}

// Return true if any bit in the bitset is set.
func (b *Bitset) Any() bool {
	return !b.None()
}

// Get a string representation of the words in the bitset.
func (b *Bitset) String() string {
	buffer := bytes.NewBufferString("")
	for i := int(wordsNeeded(b.n) - 1); i >= 0; i-- {
		fmt.Fprintf(buffer, "%032b.", b.b[i])
	}
	return string(buffer.Bytes())
}

// Make a new bitset with a starting capacity of n bits. The bitset expands
// automatically. The maximum capacity of the bitset is 4,294,967,295 bits.
func New(n uint32) *Bitset {
	return &Bitset{n, make([]uint32, wordsNeeded(n))}
}
<commit_msg>No need for the nil checks. Instances must be initialized using the New functions<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package bitset

import (
	"bytes"
	"fmt"
	"math"
)

const (
	lWord     uint32 = 32
	lLog2Word uint32 = 5
	allBits   uint32 = 0xffffffff
)

func wordsNeeded(n uint32) uint32 {
	if n == 0 {
		return 1
	} else if n == math.MaxUint32 {
		return math.MaxUint32 >> lLog2Word
	}
	return (n + (lWord - 1)) >> lLog2Word
}

type Bitset struct {
	n uint32
	b []uint32
}

// Returns the current size of the bitset.
func (b *Bitset) Len() uint32 {
	return b.n
}

/// Test whether bit n is set.
func (b *Bitset) Test(i uint32) bool {
	if i >= b.n {
		return false
	}
	return ((b.b[i>>lLog2Word] & (1 << (i & (lWord - 1)))) != 0)
}

// Set bit i to 1.
func (b *Bitset) Set(i uint32) {
	if i >= b.n {
		nsize := wordsNeeded(i + 1)
		l := uint32(len(b.b))
		if nsize > l {
			nb := make([]uint32, nsize-l)
			b.b = append(b.b, nb...)
		}
		b.n = i + 1
	}
	b.b[i>>lLog2Word] |= (1 << (i & (lWord - 1)))
}

// Set bit i to 0.
func (b *Bitset) Clear(i uint32) {
	if i >= b.n {
		return
	}
	b.b[i>>lLog2Word] &^= 1 << (i & (lWord - 1))
}

// Flip bit i.
func (b *Bitset) Flip(i uint32) {
	if i >= b.n {
		b.Set(i)
	}
	b.b[i>>lLog2Word] ^= 1 << (i & (lWord - 1))
}

// Clear all bits in the bitset.
func (b *Bitset) ClearAll() {
	for i := range b.b {
		b.b[i] = 0
	}
}

// Get the number of words used in the bitset.
func (b *Bitset) wordCount() uint32 {
	return wordsNeeded(b.n)
}

// Clone the bitset.
func (b *Bitset) Clone() *Bitset {
	c := New(b.n)
	copy(c.b, b.b)
	return c
}

// Copy the bitset into another bitset, returning the size of the destination
// bitset.
func (b *Bitset) Copy(c *Bitset) (n uint32) {
	copy(c.b, b.b)
	n = c.n
	if b.n < c.n {
		n = b.n
	}
	return
}

// http://en.wikipedia.org/wiki/Hamming_weight
const (
	m1 uint32 = 0x55555555 // 0101...
	m2 uint32 = 0x33333333 // 00110011...
	m4 uint32 = 0x0f0f0f0f // 00001111...
)

func popCountUint32(x uint32) uint32 {
	x -= (x >> 1) & m1             // put count of each 2 bits into those 2 bits
	x = (x & m2) + ((x >> 2) & m2) // put count of each 4 bits into those 4 bits
	x = (x + (x >> 4)) & m4        // put count of each 8 bits into those 8 bits
	x += x >> 8                    // put count of each 16 bits into their lowest 8 bits
	x += x >> 16                   // put count of each 32 bits into their lowest 8 bits
	return x & 0x7f
}

// Get the number of set bits in the bitset.
func (b *Bitset) Count() uint32 {
	sum := uint32(0)
	for _, w := range b.b {
		sum += popCountUint32(w)
	}
	return sum
}

// Test if two bitsets are equal. Returns true if both bitsets are the same
// size, and if all of the same bits are set in both bitsets.
func (b *Bitset) Equal(c *Bitset) bool {
	if b.n != c.n {
		return false
	}
	for p, v := range b.b {
		if c.b[p] != v {
			return false
		}
	}
	return true
}

// Bitset &^ (and or); difference between receiver and another set.
func (b *Bitset) Difference(ob *Bitset) (result *Bitset) {
	result = b.Clone() // clone b (in case b is bigger than ob)
	szl := ob.wordCount()
	l := uint32(len(b.b))
	for i := uint32(0); i < l; i++ {
		if i >= szl {
			break
		}
		result.b[i] = b.b[i] &^ ob.b[i]
	}
	return
}

func sortByLength(a *Bitset, b *Bitset) (ap *Bitset, bp *Bitset) {
	if a.n <= b.n {
		ap, bp = a, b
	} else {
		ap, bp = b, a
	}
	return
}

// Bitset & (and); intersection of receiver and another set
func (b *Bitset) Intersection(ob *Bitset) (result *Bitset) {
	b, ob = sortByLength(b, ob)
	result = New(b.n)
	for i, w := range b.b {
		result.b[i] = w & ob.b[i]
	}
	return
}

// Bitset | (or); union of receiver and another set
func (b *Bitset) Union(ob *Bitset) (result *Bitset) {
	b, ob = sortByLength(b, ob)
	result = ob.Clone()
	szl := ob.wordCount()
	l := uint32(len(b.b))
	for i := uint32(0); i < l; i++ {
		if i >= szl {
			break
		}
		result.b[i] = b.b[i] | ob.b[i]
	}
	return
}

// Bitset ^ (xor); symmetric difference of receiver and another set.
func (b *Bitset) SymmetricDifference(ob *Bitset) (result *Bitset) {
	b, ob = sortByLength(b, ob)
	// ob is bigger, so clone it
	result = ob.Clone()
	szl := b.wordCount()
	l := uint32(len(b.b))
	for i := uint32(0); i < l; i++ {
		if i >= szl {
			break
		}
		result.b[i] = b.b[i] ^ ob.b[i]
	}
	return
}

// Return true if the bitset's length is a multiple of the word size.
func (b *Bitset) isEven() bool {
	return (b.n % lWord) == 0
}

// Clean last word by setting unused bits to 0.
func (b *Bitset) cleanLastWord() {
	if !b.isEven() {
		b.b[wordsNeeded(b.n)-1] &= (allBits >> (lWord - (b.n % lWord)))
	}
}

// Return the (local) complement of a bitset (up to n bits)
func (b *Bitset) Complement() (result *Bitset) {
	b.String()
	result = New(b.n)
	for i, w := range b.b {
		result.b[i] = ^(w)
	}
	result.cleanLastWord()
	return
}

// Returns true if all bits in the bitset are set.
func (b *Bitset) All() bool {
	return b.Count() == b.n
}

// Returns true if no bit in the bitset is set.
func (b *Bitset) None() bool {
	for _, w := range b.b {
		if w > 0 {
			return false
		}
	}
	return true
}

// Return true if any bit in the bitset is set.
func (b *Bitset) Any() bool {
	return !b.None()
}

// Get a string representation of the words in the bitset.
func (b *Bitset) String() string {
	buffer := bytes.NewBufferString("")
	for i := int(wordsNeeded(b.n) - 1); i >= 0; i-- {
		fmt.Fprintf(buffer, "%032b.", b.b[i])
	}
	return string(buffer.Bytes())
}

// Make a new bitset with a starting capacity of n bits. The bitset expands
// automatically. The maximum capacity of the bitset is 4,294,967,295 bits.
func New(n uint32) *Bitset {
	return &Bitset{n, make([]uint32, wordsNeeded(n))}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"
)

type UnicodeBlock struct {
	start, end rune
}

func (b *UnicodeBlock) RandomCodePoint() rune {
	return rune(rand.Intn(int(b.end-b.start)) + int(b.start) + 1)
}

func (b *UnicodeBlock) Print() {
	for i := b.start; i <= b.end; i++ {
		if strconv.IsPrint(i) {
			fmt.Printf("%c ", i)
		}
	}
	fmt.Println()
}

// Print num random characters from block.
func (b *UnicodeBlock) PrintRandom(num int) {
	for i := 0; i < num; i++ {
		fmt.Printf("%c ", b.RandomCodePoint())
	}
	fmt.Println()
}

// implementing the flag.Value interface
func (b *UnicodeBlock) Set(value string) error {
	vals := strings.Split(value, ",")
	if len(vals) == 1 {
		end, err := strconv.ParseInt(vals[0], 0, 0)
		if err != nil {
			return err
		}
		b.end = rune(end)
	} else if len(vals) == 2 {
		start, err := strconv.ParseInt(vals[0], 0, 0)
		end, err := strconv.ParseInt(vals[1], 0, 0)
		if err != nil {
			return err
		}
		b.start = rune(start)
		b.end = rune(end)
	}
	return nil
}

// implementing the flag.Value interface
func (b *UnicodeBlock) String() string {
	return fmt.Sprint(*b)
}

// For info about fonts supporting specific unicode blocks, see for example:
// http://www.fileformat.info/info/unicode/block/index.htm
var Blocks = map[string]*UnicodeBlock{
	// Basic Multilingual Plane (0000-ffff)
	// https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
	"hebrew":       &UnicodeBlock{0x0590, 0x05ff},
	"currency":     &UnicodeBlock{0x20a0, 0x20cf},
	"letterlike":   &UnicodeBlock{0x2100, 0x214f},
	"geometric":    &UnicodeBlock{0x25a0, 0x25ff},
	"misc_symbols": &UnicodeBlock{0x2600, 0x26ff},
	"dingbats":     &UnicodeBlock{0x2700, 0x27bf},
	// Supplementary Multilingual Plane (10000-1ffff)
	// https://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Multilingual_Plane
	"aegean_nums":        &UnicodeBlock{0x10100, 0x1013f},
	"ancient_greek_nums": &UnicodeBlock{0x10140, 0x1018f},
	"phaistos_disc":      &UnicodeBlock{0x101d0, 0x101ff},
	"math_alnum":         &UnicodeBlock{0x1d400, 0x1d7ff},
	"emoji":              &UnicodeBlock{0x1f300, 0x1f5ff},
	"mahjong":            &UnicodeBlock{0x1f000, 0x1f02f},
	"dominos":            &UnicodeBlock{0x1f030, 0x1f09f},
	"playing_cards":      &UnicodeBlock{0x1f0a0, 0x1f0ff},
}
<commit_msg>Add misc_technical (2300-23ff) to Blocks<commit_after>package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"strings"
)

type UnicodeBlock struct {
	start, end rune
}

func (b *UnicodeBlock) RandomCodePoint() rune {
	return rune(rand.Intn(int(b.end-b.start)) + int(b.start) + 1)
}

func (b *UnicodeBlock) Print() {
	for i := b.start; i <= b.end; i++ {
		if strconv.IsPrint(i) {
			fmt.Printf("%c ", i)
		}
	}
	fmt.Println()
}

// Print num random characters from block.
func (b *UnicodeBlock) PrintRandom(num int) {
	for i := 0; i < num; i++ {
		fmt.Printf("%c ", b.RandomCodePoint())
	}
	fmt.Println()
}

// implementing the flag.Value interface
func (b *UnicodeBlock) Set(value string) error {
	vals := strings.Split(value, ",")
	if len(vals) == 1 {
		end, err := strconv.ParseInt(vals[0], 0, 0)
		if err != nil {
			return err
		}
		b.end = rune(end)
	} else if len(vals) == 2 {
		start, err := strconv.ParseInt(vals[0], 0, 0)
		end, err := strconv.ParseInt(vals[1], 0, 0)
		if err != nil {
			return err
		}
		b.start = rune(start)
		b.end = rune(end)
	}
	return nil
}

// implementing the flag.Value interface
func (b *UnicodeBlock) String() string {
	return fmt.Sprint(*b)
}

// For info about fonts supporting specific unicode blocks, see for example:
// http://www.fileformat.info/info/unicode/block/index.htm
var Blocks = map[string]*UnicodeBlock{
	// Basic Multilingual Plane (0000-ffff)
	// https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
	"hebrew":         &UnicodeBlock{0x0590, 0x05ff},
	"currency":       &UnicodeBlock{0x20a0, 0x20cf},
	"letterlike":     &UnicodeBlock{0x2100, 0x214f},
	"misc_technical": &UnicodeBlock{0x2300, 0x23ff},
	"geometric":      &UnicodeBlock{0x25a0, 0x25ff},
	"misc_symbols":   &UnicodeBlock{0x2600, 0x26ff},
	"dingbats":       &UnicodeBlock{0x2700, 0x27bf},
	// Supplementary Multilingual Plane (10000-1ffff)
	// https://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Multilingual_Plane
	"aegean_nums":        &UnicodeBlock{0x10100, 0x1013f},
	"ancient_greek_nums": &UnicodeBlock{0x10140, 0x1018f},
	"phaistos_disc":      &UnicodeBlock{0x101d0, 0x101ff},
	"math_alnum":         &UnicodeBlock{0x1d400, 0x1d7ff},
	"emoji":              &UnicodeBlock{0x1f300, 0x1f5ff},
	"mahjong":            &UnicodeBlock{0x1f000, 0x1f02f},
	"dominos":            &UnicodeBlock{0x1f030, 0x1f09f},
	"playing_cards":      &UnicodeBlock{0x1f0a0, 0x1f0ff},
}
<|endoftext|>