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

// Package inpututil provides utility functions of input like keyboard or mouse.
//
// Note: This package is experimental and API might be changed.
package inpututil

import (
	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/internal/hooks"
	"github.com/hajimehoshi/ebiten/internal/sync"
)

type inputState struct {
	keyStates     map[ebiten.Key]int
	prevKeyStates map[ebiten.Key]int

	mouseButtonStates     map[ebiten.MouseButton]int
	prevMouseButtonStates map[ebiten.MouseButton]int

	gamepadButtonStates     map[int]map[ebiten.GamepadButton]int
	prevGamepadButtonStates map[int]map[ebiten.GamepadButton]int

	touchStates     map[int]int
	prevTouchStates map[int]int

	m sync.RWMutex
}

var theInputState = &inputState{
	keyStates:     map[ebiten.Key]int{},
	prevKeyStates: map[ebiten.Key]int{},

	mouseButtonStates:     map[ebiten.MouseButton]int{},
	prevMouseButtonStates: map[ebiten.MouseButton]int{},

	gamepadButtonStates:     map[int]map[ebiten.GamepadButton]int{},
	prevGamepadButtonStates: map[int]map[ebiten.GamepadButton]int{},

	touchStates: map[int]int{},
}

func init() {
	hooks.AppendHookOnUpdate(func() error {
		theInputState.update()
		return nil
	})
}

func (i *inputState) update() {
	i.m.Lock()
	defer i.m.Unlock()

	// Keyboard
	for k := ebiten.Key(0); k <= ebiten.KeyMax; k++ {
		i.prevKeyStates[k] = i.keyStates[k]
		if ebiten.IsKeyPressed(k) {
			i.keyStates[k]++
		} else {
			i.keyStates[k] = 0
		}
	}

	// Mouse
	for _, b := range []ebiten.MouseButton{
		ebiten.MouseButtonLeft,
		ebiten.MouseButtonRight,
		ebiten.MouseButtonMiddle,
	} {
		i.prevMouseButtonStates[b] = i.mouseButtonStates[b]
		if ebiten.IsMouseButtonPressed(b) {
			i.mouseButtonStates[b]++
		} else {
			i.mouseButtonStates[b] = 0
		}
	}

	// Gamepads

	// Reset the previous states first since some gamepad IDs might be already gone.
	for id := range i.prevGamepadButtonStates {
		for b := range i.prevGamepadButtonStates[id] {
			i.prevGamepadButtonStates[id][b] = 0
		}
	}
	ids := map[int]struct{}{}
	for _, id := range ebiten.GamepadIDs() {
		ids[id] = struct{}{}

		if _, ok := i.prevGamepadButtonStates[id]; !ok {
			i.prevGamepadButtonStates[id] = map[ebiten.GamepadButton]int{}
		}
		if _, ok := i.gamepadButtonStates[id]; !ok {
			i.gamepadButtonStates[id] = map[ebiten.GamepadButton]int{}
		}

		n := ebiten.GamepadButtonNum(id)
		for b := ebiten.GamepadButton(0); b < ebiten.GamepadButton(n); b++ {
			i.prevGamepadButtonStates[id][b] = i.gamepadButtonStates[id][b]
			if ebiten.IsGamepadButtonPressed(id, b) {
				i.gamepadButtonStates[id][b]++
			} else {
				i.gamepadButtonStates[id][b] = 0
			}
		}
	}
	idsToDelete := []int{}
	for id := range i.gamepadButtonStates {
		if _, ok := ids[id]; !ok {
			idsToDelete = append(idsToDelete, id)
		}
	}
	for _, id := range idsToDelete {
		delete(i.gamepadButtonStates, id)
	}

	// Touches
	ids = map[int]struct{}{}

	// Reset the previous states first since some gamepad IDs might be already gone.
	for id := range i.prevTouchStates {
		i.prevTouchStates[id] = 0
	}

	for _, t := range ebiten.Touches() {
		ids[t.ID()] = struct{}{}
		i.prevTouchStates[t.ID()] = i.touchStates[t.ID()]
		i.touchStates[t.ID()]++
	}
	idsToDelete = []int{}
	for id := range i.touchStates {
		if _, ok := ids[id]; !ok {
			idsToDelete = append(idsToDelete, id)
		}
	}
	for _, id := range idsToDelete {
		delete(i.touchStates, id)
	}
}

// IsKeyJustPressed returns a boolean value indicating
// whether the given key is pressed just in the current frame.
//
// IsKeyJustPressed is concurrent safe.
func IsKeyJustPressed(key ebiten.Key) bool {
	return KeyPressDuration(key) == 1
}

// IsKeyJustReleased returns a boolean value indicating
// whether the given key is released just in the current frame.
//
// IsKeyJustReleased is concurrent safe.
func IsKeyJustReleased(key ebiten.Key) bool {
	theInputState.m.RLock()
	r := theInputState.keyStates[key] == 0 && theInputState.prevKeyStates[key] > 0
	theInputState.m.RUnlock()
	return r
}

// KeyPressDuration returns how long the key is pressed in frames.
//
// KeyPressDuration is concurrent safe.
func KeyPressDuration(key ebiten.Key) int {
	theInputState.m.RLock()
	s := theInputState.keyStates[key]
	theInputState.m.RUnlock()
	return s
}

// IsMouseButtonJustPressed returns a boolean value indicating
// whether the given mouse button is pressed just in the current frame.
//
// IsMouseButtonJustPressed is concurrent safe.
func IsMouseButtonJustPressed(button ebiten.MouseButton) bool {
	return MouseButtonPressDuration(button) == 1
}

// IsMouseButtonJustReleased returns a boolean value indicating
// whether the given mouse button is released just in the current frame.
//
// IsMouseButtonJustReleased is concurrent safe.
func IsMouseButtonJustReleased(button ebiten.MouseButton) bool {
	theInputState.m.RLock()
	r := theInputState.mouseButtonStates[button] == 0 &&
		theInputState.prevMouseButtonStates[button] > 0
	theInputState.m.RUnlock()
	return r
}

// MouseButtonPressDuration returns how long the mouse button is pressed in frames.
//
// MouseButtonPressDuration is concurrent safe.
func MouseButtonPressDuration(button ebiten.MouseButton) int {
	theInputState.m.RLock()
	s := theInputState.mouseButtonStates[button]
	theInputState.m.RUnlock()
	return s
}

// IsGamepadButtonJustPressed returns a boolean value indicating
// whether the given gamepad button of the gamepad id is pressed just in the current frame.
//
// IsGamepadButtonJustPressed is concurrent safe.
func IsGamepadButtonJustPressed(id int, button ebiten.GamepadButton) bool {
	return GamepadButtonPressDuration(id, button) == 1
}

// IsGamepadButtonJustReleased returns a boolean value indicating
// whether the given gamepad button of the gamepad id is released just in the current frame.
//
// IsGamepadButtonJustReleased is concurrent safe.
func IsGamepadButtonJustReleased(id int, button ebiten.GamepadButton) bool {
	theInputState.m.RLock()
	prev := 0
	if _, ok := theInputState.prevGamepadButtonStates[id]; ok {
		prev = theInputState.prevGamepadButtonStates[id][button]
	}
	current := 0
	if _, ok := theInputState.gamepadButtonStates[id]; ok {
		current = theInputState.gamepadButtonStates[id][button]
	}
	theInputState.m.RUnlock()
	return current == 0 && prev > 0
}

// GamepadButtonPressDuration returns how long the gamepad button of the gamepad id is pressed in frames.
//
// GamepadButtonPressDuration is concurrent safe.
func GamepadButtonPressDuration(id int, button ebiten.GamepadButton) int {
	theInputState.m.RLock()
	s := 0
	if _, ok := theInputState.gamepadButtonStates[id]; ok {
		s = theInputState.gamepadButtonStates[id][button]
	}
	theInputState.m.RUnlock()
	return s
}

// IsJustTouched returns a boolean value indicating
// whether the given touch is pressed just in the current frame.
//
// IsJustTouched is concurrent safe.
func IsJustTouched(id int) bool {
	return TouchDuration(id) == 1
}

// IsTouchJustReleased returns a boolean value indicating
// whether the given touch is released just in the current frame.
//
// IsTouchJustReleased is concurrent safe.
func IsTouchJustReleased(id int) bool {
	theInputState.m.RLock()
	r := theInputState.touchStates[id] == 0 && theInputState.prevTouchStates[id] > 0
	theInputState.m.RUnlock()
	return r
}

// TouchDuration returns how long the touch remains in frames.
//
// TouchDuration is concurrent safe.
func TouchDuration(id int) int {
	theInputState.m.RLock()
	s := theInputState.touchStates[id]
	theInputState.m.RUnlock()
	return s
}
<commit_msg>inpututil: Bug fix: Init prevTouchStates<commit_after>// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package inpututil provides utility functions of input like keyboard or mouse.
//
// Note: This package is experimental and API might be changed.
package inpututil

import (
	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/internal/hooks"
	"github.com/hajimehoshi/ebiten/internal/sync"
)

type inputState struct {
	keyStates     map[ebiten.Key]int
	prevKeyStates map[ebiten.Key]int

	mouseButtonStates     map[ebiten.MouseButton]int
	prevMouseButtonStates map[ebiten.MouseButton]int

	gamepadButtonStates     map[int]map[ebiten.GamepadButton]int
	prevGamepadButtonStates map[int]map[ebiten.GamepadButton]int

	touchStates     map[int]int
	prevTouchStates map[int]int

	m sync.RWMutex
}

var theInputState = &inputState{
	keyStates:     map[ebiten.Key]int{},
	prevKeyStates: map[ebiten.Key]int{},

	mouseButtonStates:     map[ebiten.MouseButton]int{},
	prevMouseButtonStates: map[ebiten.MouseButton]int{},

	gamepadButtonStates:     map[int]map[ebiten.GamepadButton]int{},
	prevGamepadButtonStates: map[int]map[ebiten.GamepadButton]int{},

	touchStates:     map[int]int{},
	prevTouchStates: map[int]int{},
}

func init() {
	hooks.AppendHookOnUpdate(func() error {
		theInputState.update()
		return nil
	})
}

func (i *inputState) update() {
	i.m.Lock()
	defer i.m.Unlock()

	// Keyboard
	for k := ebiten.Key(0); k <= ebiten.KeyMax; k++ {
		i.prevKeyStates[k] = i.keyStates[k]
		if ebiten.IsKeyPressed(k) {
			i.keyStates[k]++
		} else {
			i.keyStates[k] = 0
		}
	}

	// Mouse
	for _, b := range []ebiten.MouseButton{
		ebiten.MouseButtonLeft,
		ebiten.MouseButtonRight,
		ebiten.MouseButtonMiddle,
	} {
		i.prevMouseButtonStates[b] = i.mouseButtonStates[b]
		if ebiten.IsMouseButtonPressed(b) {
			i.mouseButtonStates[b]++
		} else {
			i.mouseButtonStates[b] = 0
		}
	}

	// Gamepads

	// Reset the previous states first since some gamepad IDs might be already gone.
	for id := range i.prevGamepadButtonStates {
		for b := range i.prevGamepadButtonStates[id] {
			i.prevGamepadButtonStates[id][b] = 0
		}
	}
	ids := map[int]struct{}{}
	for _, id := range ebiten.GamepadIDs() {
		ids[id] = struct{}{}

		if _, ok := i.prevGamepadButtonStates[id]; !ok {
			i.prevGamepadButtonStates[id] = map[ebiten.GamepadButton]int{}
		}
		if _, ok := i.gamepadButtonStates[id]; !ok {
			i.gamepadButtonStates[id] = map[ebiten.GamepadButton]int{}
		}

		n := ebiten.GamepadButtonNum(id)
		for b := ebiten.GamepadButton(0); b < ebiten.GamepadButton(n); b++ {
			i.prevGamepadButtonStates[id][b] = i.gamepadButtonStates[id][b]
			if ebiten.IsGamepadButtonPressed(id, b) {
				i.gamepadButtonStates[id][b]++
			} else {
				i.gamepadButtonStates[id][b] = 0
			}
		}
	}
	idsToDelete := []int{}
	for id := range i.gamepadButtonStates {
		if _, ok := ids[id]; !ok {
			idsToDelete = append(idsToDelete, id)
		}
	}
	for _, id := range idsToDelete {
		delete(i.gamepadButtonStates, id)
	}

	// Touches
	ids = map[int]struct{}{}

	// Reset the previous states first since some gamepad IDs might be already gone.
	for id := range i.prevTouchStates {
		i.prevTouchStates[id] = 0
	}

	for _, t := range ebiten.Touches() {
		ids[t.ID()] = struct{}{}
		i.prevTouchStates[t.ID()] = i.touchStates[t.ID()]
		i.touchStates[t.ID()]++
	}
	idsToDelete = []int{}
	for id := range i.touchStates {
		if _, ok := ids[id]; !ok {
			idsToDelete = append(idsToDelete, id)
		}
	}
	for _, id := range idsToDelete {
		delete(i.touchStates, id)
	}
}

// IsKeyJustPressed returns a boolean value indicating
// whether the given key is pressed just in the current frame.
//
// IsKeyJustPressed is concurrent safe.
func IsKeyJustPressed(key ebiten.Key) bool {
	return KeyPressDuration(key) == 1
}

// IsKeyJustReleased returns a boolean value indicating
// whether the given key is released just in the current frame.
//
// IsKeyJustReleased is concurrent safe.
func IsKeyJustReleased(key ebiten.Key) bool {
	theInputState.m.RLock()
	r := theInputState.keyStates[key] == 0 && theInputState.prevKeyStates[key] > 0
	theInputState.m.RUnlock()
	return r
}

// KeyPressDuration returns how long the key is pressed in frames.
//
// KeyPressDuration is concurrent safe.
func KeyPressDuration(key ebiten.Key) int {
	theInputState.m.RLock()
	s := theInputState.keyStates[key]
	theInputState.m.RUnlock()
	return s
}

// IsMouseButtonJustPressed returns a boolean value indicating
// whether the given mouse button is pressed just in the current frame.
//
// IsMouseButtonJustPressed is concurrent safe.
func IsMouseButtonJustPressed(button ebiten.MouseButton) bool {
	return MouseButtonPressDuration(button) == 1
}

// IsMouseButtonJustReleased returns a boolean value indicating
// whether the given mouse button is released just in the current frame.
//
// IsMouseButtonJustReleased is concurrent safe.
func IsMouseButtonJustReleased(button ebiten.MouseButton) bool {
	theInputState.m.RLock()
	r := theInputState.mouseButtonStates[button] == 0 &&
		theInputState.prevMouseButtonStates[button] > 0
	theInputState.m.RUnlock()
	return r
}

// MouseButtonPressDuration returns how long the mouse button is pressed in frames.
//
// MouseButtonPressDuration is concurrent safe.
func MouseButtonPressDuration(button ebiten.MouseButton) int {
	theInputState.m.RLock()
	s := theInputState.mouseButtonStates[button]
	theInputState.m.RUnlock()
	return s
}

// IsGamepadButtonJustPressed returns a boolean value indicating
// whether the given gamepad button of the gamepad id is pressed just in the current frame.
//
// IsGamepadButtonJustPressed is concurrent safe.
func IsGamepadButtonJustPressed(id int, button ebiten.GamepadButton) bool {
	return GamepadButtonPressDuration(id, button) == 1
}

// IsGamepadButtonJustReleased returns a boolean value indicating
// whether the given gamepad button of the gamepad id is released just in the current frame.
//
// IsGamepadButtonJustReleased is concurrent safe.
func IsGamepadButtonJustReleased(id int, button ebiten.GamepadButton) bool {
	theInputState.m.RLock()
	prev := 0
	if _, ok := theInputState.prevGamepadButtonStates[id]; ok {
		prev = theInputState.prevGamepadButtonStates[id][button]
	}
	current := 0
	if _, ok := theInputState.gamepadButtonStates[id]; ok {
		current = theInputState.gamepadButtonStates[id][button]
	}
	theInputState.m.RUnlock()
	return current == 0 && prev > 0
}

// GamepadButtonPressDuration returns how long the gamepad button of the gamepad id is pressed in frames.
//
// GamepadButtonPressDuration is concurrent safe.
func GamepadButtonPressDuration(id int, button ebiten.GamepadButton) int {
	theInputState.m.RLock()
	s := 0
	if _, ok := theInputState.gamepadButtonStates[id]; ok {
		s = theInputState.gamepadButtonStates[id][button]
	}
	theInputState.m.RUnlock()
	return s
}

// IsJustTouched returns a boolean value indicating
// whether the given touch is pressed just in the current frame.
//
// IsJustTouched is concurrent safe.
func IsJustTouched(id int) bool {
	return TouchDuration(id) == 1
}

// IsTouchJustReleased returns a boolean value indicating
// whether the given touch is released just in the current frame.
//
// IsTouchJustReleased is concurrent safe.
func IsTouchJustReleased(id int) bool {
	theInputState.m.RLock()
	r := theInputState.touchStates[id] == 0 && theInputState.prevTouchStates[id] > 0
	theInputState.m.RUnlock()
	return r
}

// TouchDuration returns how long the touch remains in frames.
//
// TouchDuration is concurrent safe.
func TouchDuration(id int) int {
	theInputState.m.RLock()
	s := theInputState.touchStates[id]
	theInputState.m.RUnlock()
	return s
}
<|endoftext|>


<commit_before>package services/cloudca

type Instance struct {
	Id string
}

type InstanceService interface {
	Get(id string) (Instance, error)
	GetByName(name string) (Instance, error)
	List() ([]Instance, error)
	Create(Instance)
}

type InstanceApi struct {
	entityService EntityService
}

func NewInstanceService(apiClient CCAApiClient, serviceCode string, environmentName string) *InstanceService {
	return &InstanceApi{
		"entityService": NewEntityService(apiClient, serviceCode, environmentName, INSTANCE_ENTITY_TYPE)
	}
}

func (instanceApi InstanceApi) Get(id string) (Instance, error) {
	return Instance{}, nil
}

func (instanceApi InstanceApi) GetByName(name string) (Instance, error) {
	return Instance{}, nil
}

func (instanceApi InstanceApi) GetByName(name string) (Instance, error) {
	return Instance{}, nil
}

func (instanceApi InstanceApi) List() ([]Instance, error) {
	return []Instance{}, nil
}
<commit_msg>Added extra methods to InstanceService<commit_after>package services/cloudca

type Instance struct {
	Id string
}

type InstanceService interface {
	Get(id string) (Instance, error)
	GetByName(name string) (Instance, error)
	List() ([]Instance, error)
	Create(Instance) (bool, error)
	Delete(id string, purge bool) (bool, error)
	Exists(id string) (bool, error)
}

type InstanceApi struct {
	entityService EntityService
}

func NewInstanceService(apiClient CCAApiClient, serviceCode string, environmentName string) *InstanceService {
	return &InstanceApi{
		"entityService": NewEntityService(apiClient, serviceCode, environmentName, INSTANCE_ENTITY_TYPE)
	}
}

func (instanceApi InstanceApi) Get(id string) (Instance, error) {
	return Instance{}, nil
}

func (instanceApi InstanceApi) GetByName(name string) (Instance, error) {
	return Instance{}, nil
}

func (instanceApi InstanceApi) GetByName(name string) (Instance, error) {
	return Instance{}, nil
}

func (instanceApi InstanceApi) List() ([]Instance, error) {
	return []Instance{}, nil
}

func (instanceApi InstanceApi) Create(instance Instance) (bool, error) {
	return false, nil
}

func (instanceApi InstanceApi) Delete(id string, purge bool) (bool, error) {
	return false, nil
}

func (instanceApi InstanceApi) Exists(id string) (bool, error) {
	return false, nil
}
<|endoftext|>


<commit_before>package main

import (
	"atlantis/builder/api"
	"atlantis/builder/docker"
	"flag"
)

func main() {
	var layerPath = flag.String("layer-path", "/opt/atlantis/builder/layers", "path to overlay layers")
	var manifestDir = flag.String("manifest-dir", "/opt/atlantis/builder/manifests", "dir to store manifests")
	var registry = flag.String("registry", "localhost", "the registry to use")
	var port = flag.Int("port", 8080, "port to run on")
	flag.Parse()

	docker.LogOutput = true
	api.New(uint16(*port), *registry, *layerPath, *manifestDir).Run()
}
<commit_msg>Updated builderd to use toml based config file for registry<commit_after>package main

import (
	"atlantis/builder/api"
	"atlantis/builder/docker"
	"flag"
	"github.com/BurntSushi/toml"
	"github.com/jigish/go-flags"
	"log"
)

type ServerOpts struct {
	ConfigFile string `long:"config-file" default:"/etc/atlantis/builder/server.toml" description:"the config file to use"`
	Registry   string `long:"registry" default:"localhost" description:"the registry to use")`
}

type BuilderConfig struct {
	Registry string `toml:"registry_host"`
}

func main() {
	var layerPath = flag.String("layer-path", "/opt/atlantis/builder/layers", "path to overlay layers")
	var manifestDir = flag.String("manifest-dir", "/opt/atlantis/builder/manifests", "dir to store manifests")
	var port = flag.Int("port", 8080, "port to run on")
	flag.Parse()

	builderdOpts := &ServerOpts{}
	config := &BuilderConfig{}

	parser := flags.NewParser(builderdOpts, flags.Default)
	parser.Parse()

	_, err := toml.DecodeFile(builderdOpts.ConfigFile, config)
	if err != nil {
		log.Fatalln(err)
	}
	docker.LogOutput = true
	api.New(uint16(*port), config.Registry, *layerPath, *manifestDir).Run()
}
<|endoftext|>


<commit_before>package app

import (
	"github.com/goph/emperror"
	"github.com/goph/stdlib/log"
)

// ServiceOption sets options in the Service.
type ServiceOption func(s *Service)

// Logger returns a ServiceOption that sets the logger for the service.
func Logger(l log.Logger) ServiceOption {
	return func(s *Service) {
		s.logger = l
	}
}

// ErrorHandler returns a ServiceOption that sets the error handler for the service.
func ErrorHandler(l emperror.Handler) ServiceOption {
	return func(s *Service) {
		s.errorHandler = l
	}
}

// Service contains the main controller logic.
type Service struct {
	logger       log.Logger
	errorHandler emperror.Handler
}

// NewService creates a new service object.
func NewService(opts ...ServiceOption) *Service {
	s := new(Service)

	for _, opt := range opts {
		opt(s)
	}

	// Default logger
	if s.logger == nil {
		s.logger = log.NewNopLogger()
	}

	// Default error handler
	if s.errorHandler == nil {
		s.errorHandler = emperror.NewNopHandler()
	}

	return s
}
<commit_msg>Use go-kit interface<commit_after>package app

import (
	"github.com/go-kit/kit/log"
	"github.com/goph/emperror"
)

// ServiceOption sets options in the Service.
type ServiceOption func(s *Service)

// Logger returns a ServiceOption that sets the logger for the service.
func Logger(l log.Logger) ServiceOption {
	return func(s *Service) {
		s.logger = l
	}
}

// ErrorHandler returns a ServiceOption that sets the error handler for the service.
func ErrorHandler(l emperror.Handler) ServiceOption {
	return func(s *Service) {
		s.errorHandler = l
	}
}

// Service contains the main controller logic.
type Service struct {
	logger       log.Logger
	errorHandler emperror.Handler
}

// NewService creates a new service object.
func NewService(opts ...ServiceOption) *Service {
	s := new(Service)

	for _, opt := range opts {
		opt(s)
	}

	// Default logger
	if s.logger == nil {
		s.logger = log.NewNopLogger()
	}

	// Default error handler
	if s.errorHandler == nil {
		s.errorHandler = emperror.NewNopHandler()
	}

	return s
}
<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"github.com/reflexionhealth/vanilla/sql/sqltest/ast"
	"github.com/reflexionhealth/vanilla/sql/sqltest/scanner"
	"github.com/reflexionhealth/vanilla/sql/sqltest/token"
)

// A parser.Ruleset specifies the dialect specific parsing rules for a SQL dialect
type Ruleset struct {
	ScanRules scanner.Ruleset

	CanSelectDistinctRow bool
	CanSelectWithoutFrom bool
}

type ParseError struct {
	Pos token.Position
	Msg string
}

func (e *ParseError) Error() string {
	return e.Pos.String() + ": " + e.Msg
}

// A parser holds the parser's internal state while processing
// a given text.  It can be allocated as part of another data
// structure but must be initialized via Init before use.
type Parser struct {
	scanner scanner.Scanner
	rules   Ruleset
	pos     int         // next token offset
	tok     token.Token // next token type
	lit     string      // next token literal
}

// Make initialize
func Make(src []byte, rules Ruleset) Parser {
	p := Parser{}
	p.Init(src, rules)
	return p
}

// Init prepares the parser p to convert a text src into an ast.
func (p *Parser) Init(src []byte, rules Ruleset) {
	scanError := func(pos token.Position, msg string) { p.error(pos, msg) }
	p.scanner.Init(src, scanError, rules.ScanRules)
}

// ParseStatement attempts to parse a statement or returns the first error found
func (p *Parser) ParseStatement() (stmt ast.Stmt, err error) {
	defer p.recoverStopped(&err)
	p.next() // scan first
	stmt = p.parseStatement()
	return
}

// A stopParsing panic is raised to indicate early termination.
//
// In most cases I consider panics to be a code smell when they are used for
// control flow.  In this case though, it is far easier to use a panic for
// early termination than it would be to return and check for errors everywhere.
type stopParsing struct{ err *ParseError }

func (p *Parser) stopParsing(err *ParseError) {
	panic(stopParsing{err})
}

func (p *Parser) recoverStopped(err *error) {
	if e := recover(); e != nil {
		if stop, ok := e.(stopParsing); ok {
			*err = stop.err
		} else {
			panic(e)
		}
	}
}

func (p *Parser) error(pos token.Position, msg string) {
	p.stopParsing(&ParseError{pos, msg})
}

func (p *Parser) expect(tok token.Token) {
	if p.tok != tok {
		p.error(p.scanner.Pos(), fmt.Sprintf(`expected '%v' but received '%v'.`, tok, p.tok))
	}
	p.next()
}

func (p *Parser) expected(what string) {
	p.error(p.scanner.Pos(), fmt.Sprintf(`expected '%v' but received '%v'.`, what, p.tok))
}

func (p *Parser) next() {
	p.pos, p.tok, p.lit = p.scanner.Scan()
}

func (p *Parser) parseStatement() ast.Stmt {
	switch p.tok {
	case token.SELECT:
		return p.parseSelect()
	case token.INSERT:
		return p.parseInsert()
	case token.UPDATE:
		return p.parseUpdate()
	default:
		p.expected("SELECT, INSERT, or UPDATE")
		return nil
	}
}

func (p *Parser) parseSelect() *ast.SelectStmt {
	p.expect(token.SELECT)
	stmt := &ast.SelectStmt{}
	stmt.Type = ast.SELECT_ALL
	switch p.tok {
	case token.ALL:
		p.next()
	case token.DISTINCT:
		stmt.Type = ast.SELECT_DISTINCT
		p.next()
	case token.DISTINCTROW:
		if p.rules.CanSelectDistinctRow {
			stmt.Type = ast.SELECT_DISTINCTROW
			p.next()
		} else {
			p.error(p.scanner.Pos(), `query includes SELECT "DISTINCTROW", but CanSelectDistinctRow is false`)
			p.next()
		}
	}

	if p.tok == token.ASTERISK {
		stmt.Star = true
		p.next()
	} else {
		stmt.Selection = []ast.Expr{p.parseExpression()}
		for p.tok == token.COMMA {
			stmt.Selection = append(stmt.Selection, p.parseExpression())
		}
	}

	// NOTE: The FROM clause is sometimes optional, but since this would be an
	// error in most common uses cases, the default will be that it is required
	// even for dialects where it is technically optional.
	if p.rules.CanSelectWithoutFrom && p.tok == token.EOS {
		return stmt
	}

	p.expect(token.FROM)
	switch p.tok {
	case token.IDENT:
		stmt.From.Name = p.lit
		stmt.From.Quoted = false
		p.next()
	case token.QUOTED_IDENT:
		stmt.From.Name = p.lit
		stmt.From.Quoted = true
		p.next()
	default:
		p.expected("a table name")
	}

	if p.tok == token.WHERE {
		panic("TODO: parse WHERE")
	}

	if p.tok == token.GROUP {
		panic("TODO: parse GROUP BY")
	}

	if p.tok == token.HAVING {
		panic("TODO: parse HAVING")
	}

	if p.tok == token.ORDER {
		panic("TODO: parse ORDER")
	}

	if p.tok == token.LIMIT {
		panic("TODO: parse LIMIT")
	}

	return stmt
}

func (p *Parser) parseInsert() *ast.InsertStmt {
	p.expect(token.INSERT)
	p.expect(token.INTO)
	panic("TODO: parse INSERT")
}

func (p *Parser) parseUpdate() *ast.UpdateStmt {
	p.expect(token.UPDATE)
	panic("TODO: parse UPDATE")
}

func (p *Parser) parseExpression() ast.Expr {
	switch p.tok {
	case token.IDENT:
		ident := &ast.Identifier{p.lit, false}
		p.next()
		return ident
	case token.QUOTED_IDENT:
		ident := &ast.Identifier{p.lit, true}
		p.next()
		return ident
	default:
		panic("TODO: expected ident, expression parsing hasn't been implemented yet")
	}
}
<commit_msg>sql/sqltest: fix a few bugs and add trace option to parser<commit_after>package parser

import (
	"fmt"
	"runtime"
	"strings"

	"github.com/reflexionhealth/vanilla/sql/sqltest/ast"
	"github.com/reflexionhealth/vanilla/sql/sqltest/scanner"
	"github.com/reflexionhealth/vanilla/sql/sqltest/token"
)

// A parser.Ruleset specifies the dialect specific parsing rules for a SQL dialect
type Ruleset struct {
	ScanRules scanner.Ruleset

	CanSelectDistinctRow bool
	CanSelectWithoutFrom bool
}

type ParseError struct {
	Pos token.Position
	Msg string
}

func (e *ParseError) Error() string {
	return e.Pos.String() + ": " + e.Msg
}

// A parser holds the parser's internal state while processing
// a given text.  It can be allocated as part of another data
// structure but must be initialized via Init before use.
type Parser struct {
	scanner scanner.Scanner
	rules   Ruleset

	pos int         // next token offset
	tok token.Token // next token type
	lit string      // next token literal

	Trace bool
}

// Make initialize
func Make(src []byte, rules Ruleset) Parser {
	p := Parser{}
	p.Init(src, rules)
	return p
}

// Init prepares the parser p to convert a text src into an ast.
func (p *Parser) Init(src []byte, rules Ruleset) {
	scanError := func(pos token.Position, msg string) { p.error(pos, msg) }
	p.scanner.Init(src, scanError, rules.ScanRules)
}

// ParseStatement attempts to parse a statement or returns the first error found
func (p *Parser) ParseStatement() (stmt ast.Stmt, err error) {
	defer p.recoverStopped(&err)
	p.next() // scan first
	stmt = p.parseStatement()
	return
}

// A stopParsing panic is raised to indicate early termination.
//
// In most cases I consider panics to be a code smell when they are used for
// control flow.  In this case though, it is far easier to use a panic for
// early termination than it would be to return and check for errors everywhere.
type stopParsing struct{ err *ParseError }

func (p *Parser) stopParsing(err *ParseError) {
	panic(stopParsing{err})
}

func (p *Parser) recoverStopped(err *error) {
	if e := recover(); e != nil {
		if stop, ok := e.(stopParsing); ok {
			*err = stop.err
		} else {
			panic(e)
		}
	}
}

func (p *Parser) error(pos token.Position, msg string) {
	if p.Trace {
		fmt.Printf(" (error) %v\n", (&ParseError{pos, msg}).Error())
	}
	p.stopParsing(&ParseError{pos, msg})
}

func (p *Parser) expect(tok token.Token) {
	if p.tok != tok {
		p.error(p.scanner.Pos(), fmt.Sprintf(`expected '%v' but received '%v'.`, tok, p.tok))
	}
	p.next()
}

func (p *Parser) expected(what string) {
	p.error(p.scanner.Pos(), fmt.Sprintf(`expected '%v' but received '%v'.`, what, p.tok))
}

func (p *Parser) next() {
	if p.Trace {
		pc, _, line, _ := runtime.Caller(1)
		path := strings.Split(runtime.FuncForPC(pc).Name(), ".")
		name := path[len(path)-1]
		// ignore expect and expected
		if len(name) >= 6 && name[0:6] == "expect" {
			pc, _, line, _ = runtime.Caller(2)
			path = strings.Split(runtime.FuncForPC(pc).Name(), ".")
			name = path[len(path)-1]
		}
		caller := "Parser." + name
		lit := p.lit
		if len(lit) > 7 {
			lit = lit[0:6] + "~"
		}
		// NOTE: For some irritating reason, running `go test` will always
		//       hide stderr so make sure we use stdout
		fmt.Printf(" %7.7s : %-14s @ %v:%v\n", lit, p.tok, caller, line)
	}

	p.pos, p.tok, p.lit = p.scanner.Scan()
}

func (p *Parser) parseStatement() ast.Stmt {
	switch p.tok {
	case token.SELECT:
		return p.parseSelect()
	case token.INSERT:
		return p.parseInsert()
	case token.UPDATE:
		return p.parseUpdate()
	default:
		p.expected("SELECT, INSERT, or UPDATE")
		return nil
	}
}

func (p *Parser) parseSelect() *ast.SelectStmt {
	p.expect(token.SELECT)
	stmt := &ast.SelectStmt{}
	stmt.Type = ast.SELECT_ALL
	switch p.tok {
	case token.ALL:
		p.next()
	case token.DISTINCT:
		stmt.Type = ast.SELECT_DISTINCT
		p.next()
	case token.DISTINCTROW:
		if p.rules.CanSelectDistinctRow {
			stmt.Type = ast.SELECT_DISTINCTROW
			p.next()
		} else {
			p.error(p.scanner.Pos(), `query includes SELECT "DISTINCTROW", but CanSelectDistinctRow is false`)
			p.next()
		}
	}

	if p.tok == token.ASTERISK {
		stmt.Star = true
		p.next()
	} else {
		stmt.Selection = []ast.Expr{p.parseExpression()}
		for p.tok == token.COMMA {
			p.next() // eat comma
			stmt.Selection = append(stmt.Selection, p.parseExpression())
		}
	}

	// NOTE: The FROM clause is sometimes optional, but since this would be an
	// error in most common uses cases, the default will be that it is required
	// even for dialects where it is technically optional.
	if p.rules.CanSelectWithoutFrom && p.tok == token.EOS {
		return stmt
	}

	p.expect(token.FROM)
	switch p.tok {
	case token.IDENT:
		stmt.From.Name = p.lit
		stmt.From.Quoted = false
		p.next()
	case token.QUOTED_IDENT:
		stmt.From.Name = p.lit
		stmt.From.Quoted = true
		p.next()
	default:
		p.expected("a table name")
	}

	// if p.tok == token.WHERE {
	// 	panic("TODO: parse WHERE")
	// }
	//
	// if p.tok == token.GROUP {
	// 	panic("TODO: parse GROUP BY")
	// }
	//
	// if p.tok == token.HAVING {
	// 	panic("TODO: parse HAVING")
	// }
	//
	// if p.tok == token.ORDER {
	// 	panic("TODO: parse ORDER")
	// }
	//
	// if p.tok == token.LIMIT {
	// 	panic("TODO: parse LIMIT")
	// }

	// TODO: For now we're just eating everything else until more is implemented
	for p.tok != token.EOS {
		p.next()
	}

	return stmt
}

func (p *Parser) parseInsert() *ast.InsertStmt {
	p.expect(token.INSERT)
	p.expect(token.INTO)
	panic("TODO: parse INSERT")
}

func (p *Parser) parseUpdate() *ast.UpdateStmt {
	p.expect(token.UPDATE)
	panic("TODO: parse UPDATE")
}

func (p *Parser) parseExpression() ast.Expr {
	switch p.tok {
	case token.IDENT:
		ident := &ast.Identifier{p.lit, false}
		p.next()
		return ident
	case token.QUOTED_IDENT:
		ident := &ast.Identifier{p.lit, true}
		p.next()
		return ident
	default:
		panic("TODO: expected ident, expression parsing hasn't been implemented yet")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"time"

	"github.com/tcnksm/go-httpstat"
)

func main() {
	req, err := http.NewRequest("GET", "http://deeeet.com", nil)
	if err != nil {
		log.Fatal(err)
	}

	var result httpstat.Result
	ctx := httpstat.WithHTTPStat(req.Context(), &result)
	req = req.WithContext(ctx)

	client := http.DefaultClient
	res, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()

	if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
		log.Fatal(err)
	}
	end := time.Now()

	log.Printf("Name Lookup: %d ms", int(result.NameLookup/time.Millisecond))
	log.Printf("Connect: %d ms", int(result.Connect/time.Millisecond))
	log.Printf("Start Transfer: %d ms", int(result.StartTransfer/time.Millisecond))
	log.Printf("Total: %d ms", int(result.Total(end)/time.Millisecond))
}
<commit_msg>More example<commit_after>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"time"

	"github.com/tcnksm/go-httpstat"
)

func main() {
	req, err := http.NewRequest("GET", "https://github.com", nil)
	if err != nil {
		log.Fatal(err)
	}

	var result httpstat.Result
	ctx := httpstat.WithHTTPStat(req.Context(), &result)
	req = req.WithContext(ctx)

	client := http.DefaultClient
	res, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()

	if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
		log.Fatal(err)
	}
	end := time.Now()

	log.Printf("DNS lookup: %d ms", int(result.DNSLookup/time.Millisecond))
	log.Printf("TCP connection: %d ms", int(result.TCPConnection/time.Millisecond))
	log.Printf("TLS handshake: %d ms", int(result.TLSHandshake/time.Millisecond))
	log.Printf("Server processing: %d ms", int(result.ServerProcessing/time.Millisecond))
	log.Printf("Content transfer: %d ms", int(result.ContentTransfer(time.Now())/time.Millisecond))
	fmt.Println()

	log.Printf("Name Lookup: %d ms", int(result.NameLookup/time.Millisecond))
	log.Printf("Connect: %d ms", int(result.Connect/time.Millisecond))
	log.Printf("Pre Transfer: %d ms", int(result.Pretransfer/time.Millisecond))
	log.Printf("Start Transfer: %d ms", int(result.StartTransfer/time.Millisecond))
	log.Printf("Total: %d ms", int(result.Total(end)/time.Millisecond))
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"

	"github.com/pkg/errors"
	"github.com/xshellinc/tools/constants"
	"github.com/xshellinc/tools/dialogs"
	"github.com/xshellinc/tools/lib/help"
	"github.com/xshellinc/tools/lib/ssh_helper"
)

func localesToStrings(locales []*constants.Locale) []string {
	out := make([]string, len(locales))
	for i, l := range locales {
		out[i] = l.String()
	}
	return out
}

// SetLocale is a default method to with dialog to configure the locale
func SetLocale(storage map[string]interface{}) error {

	fmt.Println("[+] Default language: ", constants.DefaultLocale)
	if dialogs.YesNoDialog("Change default language?") {
		inp := dialogs.GetSingleAnswer("New locale: ", dialogs.EmptyStringValidator, dialogs.CreateValidatorFn(constants.ValidateLocale))

		arr := constants.GetLocale(inp)

		var l string
		if len(arr) == 1 {
			l = arr[0].Locale
		} else {
			l = arr[dialogs.SelectOneDialog("Please select a locale from a list: ", localesToStrings(arr))].Locale
		}

		storage[GetConstLiteral(Locale)] = l
	}

	return nil
}

// SaveLocale is a default method to save locale into the image
func SaveLocale(storage map[string]interface{}) error {

	if _, ok := storage[GetConstLiteral(Locale)]; !ok {
		return nil
	}

	ssh, ok := storage["ssh"].(ssh_helper.Util)
	if !ok {
		return errors.New("Cannot get ssh config")
	}

	fp := help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, constants.LocaleF)
	data := fmt.Sprintf(constants.Language+constants.LocaleLang, storage[GetConstLiteral(Locale)], storage[GetConstLiteral(Locale)])

	_, eut, err := ssh.Run(fmt.Sprintf(`echo "%s" > %s`, data, fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	fp = help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, "environment")
	data = fmt.Sprintf(constants.LocaleAll, storage[GetConstLiteral(Locale)])

	_, eut, err = ssh.Run(fmt.Sprintf(`echo "%s" > %s`, data, fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	return nil
}

// SetKeyboard is a default method to with dialog to configure the keymap
func SetKeyboard(storage map[string]interface{}) error {

	fmt.Println("[+] Default keyboard: ", constants.DefaultKeymap)
	if dialogs.YesNoDialog("Change default keyboard?") {
		l := dialogs.GetSingleAnswer("New keyboard: ", dialogs.EmptyStringValidator)
		storage[GetConstLiteral(Keymap)] = fmt.Sprintf(constants.KeyMap, l)
	}

	return nil
}

// SaveKeyboard is a default method to save KEYMAP into the image
func SaveKeyboard(storage map[string]interface{}) error {

	if _, ok := storage[GetConstLiteral(Keymap)]; !ok {
		return nil
	}

	ssh, ok := storage["ssh"].(ssh_helper.Util)
	if !ok {
		return errors.New("Cannot get ssh config")
	}

	fp := help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, constants.KeyboardF)
	data := storage[GetConstLiteral(Keymap)]

	_, eut, err := ssh.Run(fmt.Sprintf(`echo "%s" > %s`, data, fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	return nil
}

// SetWifi is a dialog asking to configure wpa supplicant
func SetWifi(storage map[string]interface{}) error {
	if dialogs.YesNoDialog("Would you like to configure your WI-Fi?") {
		storage[GetConstLiteral(Wifi)+"_name"] = dialogs.GetSingleAnswer("WIFI SSID name: ", dialogs.EmptyStringValidator)
		storage[GetConstLiteral(Wifi)+"_pass"] = []byte(dialogs.WiFiPassword())
	}

	return nil
}

// SaveWifi is a default method to save wpa_supplicant for the wifi connection
func SaveWifi(storage map[string]interface{}) error {

	if _, ok := storage[GetConstLiteral(Wifi)+"_name"]; !ok {
		return nil
	}

	ssh, ok := storage["ssh"].(ssh_helper.Util)
	if !ok {
		return errors.New("Cannot get ssh config")
	}

	fp := help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, "wpa_supplicant", constants.WPAsupplicant)
	data := fmt.Sprintf(constants.WPAconf, storage[GetConstLiteral(Wifi)+"_name"], storage[GetConstLiteral(Wifi)+"_pass"])

	_, eut, err := ssh.Run(fmt.Sprintf(`echo "%s" > %s`, data, fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	return nil
}

// SetInterface is a dialog asking to setup user Interfaces for the static ip functionality
func SetInterface(storage map[string]interface{}) error {
	device := []string{"eth0", "wlan0"}
	i := Interfaces{
		Address: "192.168.0.254",
		Netmask: "255.255.255.0",
		Gateway: "192.168.0.1",
		DNS:     "192.168.0.1",
	}

	if dialogs.YesNoDialog("Would you like to assign static IP address for your device?") {
		fmt.Println("[+] Available network interface: ")
		num := dialogs.SelectOneDialog("Please select a network interface:", device)
		fmt.Println("[+] ********NOTE: ADJUST THESE VALUES ACCORDING TO YOUR LOCAL NETWORK CONFIGURATION********")

		for {
			fmt.Printf("[+] Current values are:\n \t[+] Address:%s\n\t[+] Gateway:%s\n\t[+] Netmask:%s\n\t[+] DNS:%s\n",
				i.Address, i.Gateway, i.Netmask, i.DNS)

			if dialogs.YesNoDialog("Change values?") {
				SetInterfaces(&i)

				switch device[num] {
				case "eth0":
					storage[GetConstLiteral(Interface)] = fmt.Sprintf(constants.InterfaceETH, i.Address, i.Netmask, i.Gateway, i.DNS)
					fmt.Println("[+]  Ethernet interface configuration was updated")
				case "wlan0":
					storage[GetConstLiteral(Interface)] = fmt.Sprintf(constants.InterfaceWLAN, i.Address, i.Netmask, i.Gateway, i.DNS)
					fmt.Println("[+]  wifi interface configuration was updated")
				}
			} else {
				break
			}
		}
	}

	return nil
}

// SaveInterface is a default method to save user Interfaces into the image
func SaveInterface(storage map[string]interface{}) error {

	if _, ok := storage[GetConstLiteral(Interface)]; !ok {
		return nil
	}

	ssh, ok := storage["ssh"].(ssh_helper.Util)
	if !ok {
		return errors.New("Cannot get ssh config")
	}

	fp := help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, "network", constants.InterfacesF)

	_, eut, err := ssh.Run(fmt.Sprintf(`echo "%s" > %s`, storage[GetConstLiteral(Interface)], fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	return nil
}

// SetSecondaryDNS is a dialog asking to set 8.8.8.8 DNS
func SetSecondaryDNS(storage map[string]interface{}) error {
	if dialogs.YesNoDialog("Add Google DNS as a secondary NameServer") {
		storage[GetConstLiteral(DNS)] = true
		return nil
	}

	return nil
}

// SaveSecondaryDNS is a default method to set 8.8.8.8 as a secondary DNS
func SaveSecondaryDNS(storage map[string]interface{}) error {

	if _, ok := storage[GetConstLiteral(DNS)]; !ok {
		return nil
	}

	ssh, ok := storage["ssh"].(ssh_helper.Util)
	if !ok {
		return errors.New("Cannot get ssh config")
	}

	fp := help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, "dhcp", "dhclient.conf")
	command := "append domain-name-servers 8.8.8.8, 8.8.4.4;"

	_, eut, err := ssh.Run(fmt.Sprintf(`echo "%s" >> %s`, command, fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	return nil
}
<commit_msg>More polishing<commit_after>package config

import (
	"fmt"
	"strings"

	"github.com/pkg/errors"
	"github.com/xshellinc/tools/constants"
	"github.com/xshellinc/tools/dialogs"
	"github.com/xshellinc/tools/lib/help"
	"github.com/xshellinc/tools/lib/ssh_helper"
)

// SetLocale is a default method to with dialog to configure the locale
func SetLocale(storage map[string]interface{}) error {

	fmt.Println("[+] Default language: ", constants.DefaultLocale)
	if dialogs.YesNoDialog("Change default language?") {
		inp := dialogs.GetSingleAnswer("New locale: ", dialogs.EmptyStringValidator, dialogs.CreateValidatorFn(constants.ValidateLocale))

		arr := constants.GetLocale(inp)

		var l string
		if len(arr) == 1 {
			l = arr[0].Locale
		} else {
			l = arr[dialogs.SelectOneDialog("Please select a locale from a list: ", arr.Strings())].Locale
		}

		storage[GetConstLiteral(Locale)] = l
	}

	return nil
}

// SaveLocale is a default method to save locale into the image
func SaveLocale(storage map[string]interface{}) error {

	if _, ok := storage[GetConstLiteral(Locale)]; !ok {
		return nil
	}

	ssh, ok := storage["ssh"].(ssh_helper.Util)
	if !ok {
		return errors.New("Cannot get ssh config")
	}

	fp := help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, constants.LocaleF)
	data := fmt.Sprintf(constants.Language+constants.LocaleLang, storage[GetConstLiteral(Locale)], storage[GetConstLiteral(Locale)])

	_, eut, err := ssh.Run(fmt.Sprintf(`echo "%s" > %s`, data, fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	fp = help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, "environment")
	data = fmt.Sprintf(constants.LocaleAll, storage[GetConstLiteral(Locale)])

	_, eut, err = ssh.Run(fmt.Sprintf(`echo "%s" > %s`, data, fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	return nil
}

// SetKeyboard is a default method to with dialog to configure the keymap
func SetKeyboard(storage map[string]interface{}) error {
	var (
		locale string
		ok     bool
	)

	if locale, ok = storage[GetConstLiteral(Locale)].(string); ok {
		if i := strings.IndexAny(locale, "_."); i >= 0 {
			locale = locale[:i]
		}
	}

	fmt.Println("[+] Default keyboard layout: ", constants.DefaultKeymap)

	if dialogs.YesNoDialog("Change default keyboard layout?") {
		inp := dialogs.GetSingleAnswer("New keyboard layout: ",
			dialogs.EmptyStringValidator,
			dialogs.CreateValidatorFn(func(layout string) error { return constants.ValidateLayout(locale, layout) }))

		arr := constants.GetLayout(locale, inp)

		var l string
		if len(arr) == 1 {
			l = arr[0].Layout
		} else {
			l = arr[dialogs.SelectOneDialog("Please select a layout from a list: ", arr.Strings())].Layout
		}

		storage[GetConstLiteral(Keymap)] = fmt.Sprintf(constants.KeyMap, l)
	}

	return nil
}

// SaveKeyboard is a default method to save KEYMAP into the image
func SaveKeyboard(storage map[string]interface{}) error {

	if _, ok := storage[GetConstLiteral(Keymap)]; !ok {
		return nil
	}

	ssh, ok := storage["ssh"].(ssh_helper.Util)
	if !ok {
		return errors.New("Cannot get ssh config")
	}

	fp := help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, constants.KeyboardF)
	data := storage[GetConstLiteral(Keymap)]

	_, eut, err := ssh.Run(fmt.Sprintf(`echo "%s" > %s`, data, fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	return nil
}

// SetWifi is a dialog asking to configure wpa supplicant
func SetWifi(storage map[string]interface{}) error {
	if dialogs.YesNoDialog("Would you like to configure your WI-Fi?") {
		storage[GetConstLiteral(Wifi)+"_name"] = dialogs.GetSingleAnswer("WIFI SSID name: ", dialogs.EmptyStringValidator)
		storage[GetConstLiteral(Wifi)+"_pass"] = []byte(dialogs.WiFiPassword())
	}

	return nil
}

// SaveWifi is a default method to save wpa_supplicant for the wifi connection
func SaveWifi(storage map[string]interface{}) error {

	if _, ok := storage[GetConstLiteral(Wifi)+"_name"]; !ok {
		return nil
	}

	ssh, ok := storage["ssh"].(ssh_helper.Util)
	if !ok {
		return errors.New("Cannot get ssh config")
	}

	fp := help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, "wpa_supplicant", constants.WPAsupplicant)
	data := fmt.Sprintf(constants.WPAconf, storage[GetConstLiteral(Wifi)+"_name"], storage[GetConstLiteral(Wifi)+"_pass"])

	_, eut, err := ssh.Run(fmt.Sprintf(`echo "%s" > %s`, data, fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	return nil
}

// SetInterface is a dialog asking to setup user Interfaces for the static ip functionality
func SetInterface(storage map[string]interface{}) error {
	device := []string{"eth0", "wlan0"}
	i := Interfaces{
		Address: "192.168.0.254",
		Netmask: "255.255.255.0",
		Gateway: "192.168.0.1",
		DNS:     "192.168.0.1",
	}

	if dialogs.YesNoDialog("Would you like to assign static IP address for your device?") {
		fmt.Println("[+] Available network interface: ")
		num := dialogs.SelectOneDialog("Please select a network interface:", device)
		fmt.Println("[+] ********NOTE: ADJUST THESE VALUES ACCORDING TO YOUR LOCAL NETWORK CONFIGURATION********")

		for {
			fmt.Printf("[+] Current values are:\n \t[+] Address:%s\n\t[+] Gateway:%s\n\t[+] Netmask:%s\n\t[+] DNS:%s\n",
				i.Address, i.Gateway, i.Netmask, i.DNS)

			if dialogs.YesNoDialog("Change values?") {
				SetInterfaces(&i)

				switch device[num] {
				case "eth0":
					storage[GetConstLiteral(Interface)] = fmt.Sprintf(constants.InterfaceETH, i.Address, i.Netmask, i.Gateway, i.DNS)
					fmt.Println("[+]  Ethernet interface configuration was updated")
				case "wlan0":
					storage[GetConstLiteral(Interface)] = fmt.Sprintf(constants.InterfaceWLAN, i.Address, i.Netmask, i.Gateway, i.DNS)
					fmt.Println("[+]  wifi interface configuration was updated")
				}
			} else {
				break
			}
		}
	}

	return nil
}

// SaveInterface is a default method to save user Interfaces into the image
func SaveInterface(storage map[string]interface{}) error {

	if _, ok := storage[GetConstLiteral(Interface)]; !ok {
		return nil
	}

	ssh, ok := storage["ssh"].(ssh_helper.Util)
	if !ok {
		return errors.New("Cannot get ssh config")
	}

	fp := help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, "network", constants.InterfacesF)

	_, eut, err := ssh.Run(fmt.Sprintf(`echo "%s" > %s`, storage[GetConstLiteral(Interface)], fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	return nil
}

// SetSecondaryDNS is a dialog asking to set 8.8.8.8 DNS
func SetSecondaryDNS(storage map[string]interface{}) error {
	if dialogs.YesNoDialog("Add Google DNS as a secondary NameServer") {
		storage[GetConstLiteral(DNS)] = true
		return nil
	}

	return nil
}

// SaveSecondaryDNS is a default method to set 8.8.8.8 as a secondary DNS
func SaveSecondaryDNS(storage map[string]interface{}) error {

	if _, ok := storage[GetConstLiteral(DNS)]; !ok {
		return nil
	}

	ssh, ok := storage["ssh"].(ssh_helper.Util)
	if !ok {
		return errors.New("Cannot get ssh config")
	}

	fp := help.AddPathSuffix("unix", constants.MountDir, constants.ISAAX_CONF_DIR, "dhcp", "dhclient.conf")
	command := "append domain-name-servers 8.8.8.8, 8.8.4.4;"

	_, eut, err := ssh.Run(fmt.Sprintf(`echo "%s" >> %s`, command, fp))
	if err != nil {
		return errors.New(err.Error() + ":" + eut)
	}

	return nil
}
<|endoftext|>


<commit_before><commit_msg>Fix truncation when saving file changes; closes pterodactyl/panel#1956<commit_after><|endoftext|>


<commit_before>/*
Package aiff is a AIFF/AIFC parser that extracts the basic information and allows developers to customize the parsing experienced.

Besides the parsing functionaity, this package also provides a way for developers to access the duration of an aiff/aifc file.

*/
package aiff
<commit_msg>updated documentation<commit_after>/*
Package aiff is a AIFF/AIFC parser that extracts the basic information and allows developers to customize the parsing experienced.

Besides the parsing functionality, this package also provides a way for developers to access the duration of an aiff/aifc file.
For an example of how to use the custom parser, look at the aiffinfo CLI tool which uses `NewParser` constructor and a channel
to receive chunks.

*/
package aiff
<|endoftext|>


<commit_before>package v2

import (
	"encoding/json"
	"fmt"
	"net/http"
	"reflect"
	"strings"

	"github.com/laincloud/lainlet/api"
	"github.com/laincloud/lainlet/auth"
	"github.com/laincloud/lainlet/watcher"
	"github.com/laincloud/lainlet/watcher/podgroup"
	"errors"
)

var tooManyDeadContainersError = errors.New("over half of the containers lost their IPs")

type ContainerForWebrouter struct {
	IP     string `json:"ContainerIp"`
	Expose int
}

type PodInfoForWebrouter struct {
	Annotation string
	Containers []ContainerForWebrouter `json:"ContainerInfos"`
}

// Coreinfo type
type CoreInfoForWebrouter struct {
	PodInfos []PodInfoForWebrouter
}

// Coreinfo API
type WebrouterInfo struct {
	Data map[string]CoreInfoForWebrouter
}

func (wi *WebrouterInfo) Decode(r []byte) error {
	return json.Unmarshal(r, &wi.Data)
}

func (wi *WebrouterInfo) Encode() ([]byte, error) {
	return json.Marshal(wi.Data)
}

func (wi *WebrouterInfo) URI() string {
	return "/webrouter/webprocs"
}

func (wi *WebrouterInfo) WatcherName() string {
	return watcher.PODGROUP
}

func (wi *WebrouterInfo) Make(data map[string]interface{}) (api.API, bool, error) {
	ret := &WebrouterInfo{
		Data: make(map[string]CoreInfoForWebrouter),
	}
	var containerCount, aliveCount int
	for _, item := range data {
		pg := item.(podgroup.PodGroup)
		parts := strings.Split(pg.Spec.Name, ".")
		// Webrouter only cares about web procs
		if len(parts) < 3 || parts[len(parts)-2] != "web" {
			continue
		}
		ci := CoreInfoForWebrouter{
			PodInfos: make([]PodInfoForWebrouter, len(pg.Pods)),
		}
		for i, pod := range pg.Pods {
			containerCount++
			ci.PodInfos[i] = PodInfoForWebrouter{
				Annotation: pg.Spec.Pod.Annotation,
				Containers: make([]ContainerForWebrouter, len(pod.Containers)),
			}
			if (len(pod.Containers) > 0 && len(pod.Containers[0].ContainerIp) > 0) {
				aliveCount++
			}
			for j, container := range pod.Containers {
				ci.PodInfos[i].Containers[j] = ContainerForWebrouter{
					IP:     container.ContainerIp,
					Expose: pg.Spec.Pod.Containers[j].Expose,
				}
			}
		}
		ret.Data[pg.Spec.Name] = ci
	}
	if containerCount == 0 || aliveCount * 2 < containerCount {
		return ret, false, tooManyDeadContainersError
	}
	return ret, !reflect.DeepEqual(wi.Data, ret.Data), nil
}

func (wi *WebrouterInfo) Key(r *http.Request) (string, error) {
	appName := api.GetString(r, "appname", "*")
	if !auth.Pass(r.RemoteAddr, appName) {
		if appName == "*" { // try to set the appname automatically by remoteip
			appName, err := auth.AppName(r.RemoteAddr)
			if err != nil {
				return "", fmt.Errorf("authorize failed, can not confirm the app by request ip")
			}
			return fixPrefix(appName), nil
		}
		return "", fmt.Errorf("authorize failed, no permission")
	}
	if appName != "*" {
		appName = fixPrefix(appName)
	}
	return appName, nil
}
<commit_msg>support ABTest<commit_after>package v2

import (
	"encoding/json"
	"fmt"
	"net/http"
	"reflect"
	"strings"

	"errors"
	"github.com/laincloud/lainlet/api"
	"github.com/laincloud/lainlet/auth"
	"github.com/laincloud/lainlet/watcher"
	"github.com/laincloud/lainlet/watcher/podgroup"
)

var tooManyDeadContainersError = errors.New("over half of the containers lost their IPs")

type ContainerForWebrouter struct {
	IP     string `json:"ContainerIp"`
	Expose int
}

type PodInfoForWebrouter struct {
	Annotation string
	Containers []ContainerForWebrouter `json:"ContainerInfos"`
}

// Coreinfo type
type CoreInfoForWebrouter struct {
	PodInfos []PodInfoForWebrouter
}

// Coreinfo API
type WebrouterInfo struct {
	Data map[string]CoreInfoForWebrouter
}

func (wi *WebrouterInfo) Decode(r []byte) error {
	return json.Unmarshal(r, &wi.Data)
}

func (wi *WebrouterInfo) Encode() ([]byte, error) {
	return json.Marshal(wi.Data)
}

func (wi *WebrouterInfo) URI() string {
	return "/webrouter/webprocs"
}

func (wi *WebrouterInfo) WatcherName() string {
	return watcher.PODGROUP
}

func (wi *WebrouterInfo) Make(data map[string]interface{}) (api.API, bool, error) {
	ret := &WebrouterInfo{
		Data: make(map[string]CoreInfoForWebrouter),
	}
	var containerCount, aliveCount int
	for _, item := range data {
		pg := item.(podgroup.PodGroup)
		parts := strings.Split(pg.Spec.Name, ".")
		// Webrouter only cares about web procs
		if len(parts) < 3 || (parts[len(parts)-2] != "web" && parts[len(parts)-2] != "canary") {
			continue
		}
		ci := CoreInfoForWebrouter{
			PodInfos: make([]PodInfoForWebrouter, len(pg.Pods)),
		}
		for i, pod := range pg.Pods {
			containerCount++
			ci.PodInfos[i] = PodInfoForWebrouter{
				Annotation: pg.Spec.Pod.Annotation,
				Containers: make([]ContainerForWebrouter, len(pod.Containers)),
			}
			if len(pod.Containers) > 0 && len(pod.Containers[0].ContainerIp) > 0 {
				aliveCount++
			}
			for j, container := range pod.Containers {
				ci.PodInfos[i].Containers[j] = ContainerForWebrouter{
					IP:     container.ContainerIp,
					Expose: pg.Spec.Pod.Containers[j].Expose,
				}
			}
		}
		ret.Data[pg.Spec.Name] = ci
	}
	if containerCount == 0 || aliveCount*2 < containerCount {
		return ret, false, tooManyDeadContainersError
	}
	return ret, !reflect.DeepEqual(wi.Data, ret.Data), nil
}

func (wi *WebrouterInfo) Key(r *http.Request) (string, error) {
	appName := api.GetString(r, "appname", "*")
	if !auth.Pass(r.RemoteAddr, appName) {
		if appName == "*" { // try to set the appname automatically by remoteip
			appName, err := auth.AppName(r.RemoteAddr)
			if err != nil {
				return "", fmt.Errorf("authorize failed, can not confirm the app by request ip")
			}
			return fixPrefix(appName), nil
		}
		return "", fmt.Errorf("authorize failed, no permission")
	}
	if appName != "*" {
		appName = fixPrefix(appName)
	}
	return appName, nil
}
<|endoftext|>


<commit_before>package scalyr

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"time"
)

var _config Config
var _scalyrEventsWrapper scalyrEventsWrapper
var _scalyrEvents []scalyrEvent

type Application interface {
	Event(sev Severity, attributes interface{})
}

type app struct {
	config Config
}

//
// event should accept Severity ( 0 - 6 ??, 3 being info:  and a message :  and 1 or more additional attributes)
// The "sev" (severity) field should range from 0 to 6, and identifies the importance of this event, using the
//  classic scale "finest, finer, fine, info, warning, error, fatal". This field is optional (defaults to 3 / info).
//
func (app *app) Event(sev Severity, attributes interface{}) {
	//Print(message)
	//Print(string(sev))

	se := &scalyrEvent{
		TS:    strconv.FormatInt(time.Now().UnixNano(), 10),
		Type:  0,
		Sev:   int(sev),
		Attrs: attributes,
	}

	if _scalyrEvents == nil {

		_scalyrEvents := make([]scalyrEvent, 1)
		_scalyrEvents[0] = *se

	} else {
		_scalyrEvents = append(_scalyrEvents, *se)
	}

}

//
// returns a new config struct configured with values...
//
func NewApplication(config Config) Application {

	_config = config

	a := &app{}

	initialize()

	start()

	return a
}

func initialize() {
	si := &scalyrSessionInfo{
		ServerType: "server type...",
		ServerId:   _APPLICATION_HOSTNAME,
	}

	_scalyrEventsWrapper := &scalyrEventsWrapper{
		Token:       _config.ScalyrEventWriteKey,
		Session:     _APPLICATION_PROCESS_ID,
		SessionInfo: *si,
		Events:      nil,
	}

	Print(_config.LocalLog, "Events wrapper created: ", _scalyrEventsWrapper)
}

func start() {

	go func() {
		for range ticker.C {
			flush()
		}
	}()

}

func flush() {
	Print(_config.LocalLog, "Flushing events NOW. ", nil)

	_scalyrEventsWrapper.Events = _scalyrEvents

	json, _ := json.Marshal(_scalyrEventsWrapper)
	fmt.Println(string(json))

	url := _SCALYR_ADDEVENTS_ENDPOINT
	fmt.Println("URL:>", url)
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(json))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	fmt.Println("response Status:", resp.Status)
	fmt.Println("response Headers:", resp.Header)
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println("response Body:", string(body))
}
<commit_msg>more print statements<commit_after>package scalyr

import (
	"bytes"
	"encoding/json"
	"net/http"
	"strconv"
	"time"
)

var _config Config
var _scalyrEventsWrapper scalyrEventsWrapper
var _scalyrEvents []scalyrEvent

type Application interface {
	Event(sev Severity, attributes interface{})
}

type app struct {
	config Config
}

//
// event should accept Severity ( 0 - 6 ??, 3 being info:  and a message :  and 1 or more additional attributes)
// The "sev" (severity) field should range from 0 to 6, and identifies the importance of this event, using the
//  classic scale "finest, finer, fine, info, warning, error, fatal". This field is optional (defaults to 3 / info).
//
func (app *app) Event(sev Severity, attributes interface{}) {
	//Print(message)
	//Print(string(sev))

	se := &scalyrEvent{
		TS:    strconv.FormatInt(time.Now().UnixNano(), 10),
		Type:  0,
		Sev:   int(sev),
		Attrs: attributes,
	}

	if _scalyrEvents == nil {

		_scalyrEvents := make([]scalyrEvent, 1)
		_scalyrEvents[0] = *se

	} else {
		_scalyrEvents = append(_scalyrEvents, *se)
	}

}

//
// returns a new config struct configured with values...
//
func NewApplication(config Config) Application {

	_config = config

	a := &app{}

	initialize()

	start()

	return a
}

func initialize() {
	si := &scalyrSessionInfo{
		ServerType: "server type...",
		ServerId:   _APPLICATION_HOSTNAME,
	}

	_scalyrEventsWrapper := &scalyrEventsWrapper{
		Token:       _config.ScalyrEventWriteKey,
		Session:     _APPLICATION_PROCESS_ID,
		SessionInfo: *si,
		Events:      nil,
	}

	Print(_config.LocalLog, "Events wrapper created: ", _scalyrEventsWrapper)
}

func start() {

	go func() {
		for range ticker.C {
			flush()
		}
	}()

}

func flush() {
	Print(_config.LocalLog, "Flushing events NOW. ", nil)

	_scalyrEventsWrapper.Events = _scalyrEvents

	json, _ := json.Marshal(_scalyrEventsWrapper)

	Print(_config.LocalLog, "Events being sent to scalyre: ", string(json))
	//fmt.Println(string(json))

	url := _SCALYR_ADDEVENTS_ENDPOINT

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(json))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	Print(_config.LocalLog, "Status that came back from Scalyr: ", resp.Status)

	//fmt.Println("response Status:", resp.Status)
	//fmt.Println("response Headers:", resp.Header)
	//body, _ := ioutil.ReadAll(resp.Body)
	//fmt.Println("response Body:", string(body))
}
<|endoftext|>


<commit_before>// Package implementation controller and URL routing
package caffmux

import (
	"fmt"
	"github.com/tjz101/caffmux/logs"
	"net/http"
)

var (
	StaticPath map[string]string
)

// Initialize the related, such as log initialize...
func init() {
	CaffLogger = logs.NewLogger()
	err := CaffLogger.SetLogger("console", "")
	if err != nil {
		fmt.Println("init console log error:", err)
	}
	CaffLogger.SetEnableFuncCallDepth(true)
}

type Application struct {
	Handlers *ControllerRegistor
}

func NewApplication() *Application {
	cr := NewControllerRegistor()
	return &Application{cr}
}

func (app *Application) addStaticPath(url string, path string) *Application {
	StaticPath[url] = path
	return app
}

// Run the HTTP service, addr for listening on port, such as :8080
func (app *Application) Run(addr string) error {
	CaffLogger.Debug(addr)
	return http.ListenAndServe(addr, app.Handlers)
}

// Configuration controller URL routing rules, support for regular expressions
func (app *Application) Router(path string, c ControllerInterface) *Application {
	CaffLogger.Debug(path)
	app.Handlers.Add(path, c)
	return app
}
<commit_msg>add static file setting<commit_after>// Package implementation controller and URL routing
package caffmux

import (
	"fmt"
	"github.com/tjz101/caffmux/logs"
	"net/http"
)

var (
	StaticPath map[string]string
)

// Initialize the related, such as log initialize...
func init() {
	CaffLogger = logs.NewLogger()
	err := CaffLogger.SetLogger("console", "")
	if err != nil {
		fmt.Println("init console log error:", err)
	}
	CaffLogger.SetEnableFuncCallDepth(true)
}

type Application struct {
	Handlers *ControllerRegistor
}

func NewApplication() *Application {
	cr := NewControllerRegistor()
	return &Application{cr}
}

// To add a static route
func (app *Application) AddStaticPath(url string, path string) *Application {
	StaticPath[url] = path
	return app
}

// Run the HTTP service, addr for listening on port, such as :8080
func (app *Application) Run(addr string) error {
	CaffLogger.Debug(addr)
	return http.ListenAndServe(addr, app.Handlers)
}

// Configuration controller URL routing rules, support for regular expressions
func (app *Application) Router(path string, c ControllerInterface) *Application {
	CaffLogger.Debug(path)
	app.Handlers.Add(path, c)
	return app
}
<|endoftext|>


<commit_before>/*
 * ZGrab Copyright 2015 Regents of the University of Michigan
 *
 * 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 telnet

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"math"
	"net"
)

// RFC 854 - https://tools.ietf.org/html/rfc854
const (
	IAC                = byte(255) //Interpret as command
	DONT               = byte(254)
	DO                 = byte(253)
	WONT               = byte(252)
	WILL               = byte(251)
	GO_AHEAD           = byte(249) // Special go ahead command
	IAC_CMD_LENGTH     = 3         // IAC commands take 3 bytes (inclusive)
	READ_BUFFER_LENGTH = 8192
)

func GetTelnetBanner(logStruct *TelnetLog, conn net.Conn, maxReadSize int) (err error) {
	if err = NegotiateOptions(logStruct, conn); err != nil {
		return err
	}

	//grab banner
	buffer := make([]byte, READ_BUFFER_LENGTH)

	numBytes := len(buffer)
	rounds := int(math.Ceil(float64(maxReadSize) / READ_BUFFER_LENGTH))
	count := 0
	for numBytes != 0 && count < rounds && numBytes == READ_BUFFER_LENGTH {

		numBytes, err = conn.Read(buffer)
		if err != nil && err != io.EOF {
			return err
		}

		if containsIAC(buffer) {
			continue
		}

		if count == rounds-1 {
			logStruct.Banner = logStruct.Banner + string(buffer[0:maxReadSize%READ_BUFFER_LENGTH])
		} else {
			logStruct.Banner = logStruct.Banner + string(buffer[0:numBytes])
		}
		count += 1
	}

	return nil
}

func NegotiateOptions(logStruct *TelnetLog, conn net.Conn) error {
	var readBuffer, retBuffer []byte
	var option, optionType, returnOptionType byte
	var iacIndex, firstUnreadIndex, numBytes, numDataBytes int
	var err error

	for finishedNegotiating := false; finishedNegotiating == false; {
		readBuffer = make([]byte, READ_BUFFER_LENGTH)
		retBuffer = nil
		numBytes, err = conn.Read(readBuffer)
		numDataBytes = numBytes

		if err != nil {
			return err
		}

		if numBytes == len(readBuffer) {
			return errors.New("Not enough buffer space for telnet options")
		}

		// Negotiate options

		for iacIndex = bytes.IndexByte(readBuffer, IAC); iacIndex != -1; iacIndex = bytes.IndexByte(readBuffer, IAC) {
			firstUnreadIndex = 0
			optionType = readBuffer[iacIndex+1]
			option = readBuffer[iacIndex+2]

			// ignore go ahead
			if optionType == GO_AHEAD {
				readBuffer = readBuffer[0:iacIndex]
				numBytes = iacIndex
				firstUnreadIndex = 0
				break
			}

			// record all offered options
			if optionType == WILL || optionType == DO {
				logStruct.SupportedOpts = append(logStruct.SupportedOpts, fmt.Sprintf("%d", option))
			} else if optionType == WONT || optionType == DONT {
				logStruct.UnsupportedOpts = append(logStruct.UnsupportedOpts, fmt.Sprintf("%d", option))
			}

			// reject all offered options
			if optionType == WILL || optionType == WONT {
				returnOptionType = DONT
			} else if optionType == DO || optionType == DONT {
				returnOptionType = WONT
			} else {
				return errors.New("Unsupported telnet IAC option type" + fmt.Sprintf("%d", optionType))
			}

			retBuffer = append(retBuffer, IAC)
			retBuffer = append(retBuffer, returnOptionType)
			retBuffer = append(retBuffer, option)

			firstUnreadIndex = iacIndex + IAC_CMD_LENGTH
			numDataBytes -= firstUnreadIndex
			readBuffer = readBuffer[firstUnreadIndex:]
		}

		if _, err = conn.Write(retBuffer); err != nil {
			return err
		}

		numIACBytes := numBytes - numDataBytes
		finishedNegotiating = numBytes != numIACBytes
	}

	// no more IAC commands, just read the resulting data
	if numDataBytes >= 0 {
		logStruct.Banner = string(readBuffer[0:numBytes])
	}

	return nil
}

func containsIAC(buffer []byte) bool {
	return bytes.IndexByte(buffer, IAC) != -1
}
<commit_msg>ignore timeout if the banner is already set<commit_after>/*
 * ZGrab Copyright 2015 Regents of the University of Michigan
 *
 * 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 telnet

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"math"
	"net"
)

// RFC 854 - https://tools.ietf.org/html/rfc854
const (
	IAC                = byte(255) //Interpret as command
	DONT               = byte(254)
	DO                 = byte(253)
	WONT               = byte(252)
	WILL               = byte(251)
	GO_AHEAD           = byte(249) // Special go ahead command
	IAC_CMD_LENGTH     = 3         // IAC commands take 3 bytes (inclusive)
	READ_BUFFER_LENGTH = 8192
)

func GetTelnetBanner(logStruct *TelnetLog, conn net.Conn, maxReadSize int) (err error) {
	if err = NegotiateOptions(logStruct, conn); err != nil {
		return err
	}

	//grab banner
	buffer := make([]byte, READ_BUFFER_LENGTH)

	numBytes := len(buffer)
	rounds := int(math.Ceil(float64(maxReadSize) / READ_BUFFER_LENGTH))
	count := 0
	for numBytes != 0 && count < rounds && numBytes == READ_BUFFER_LENGTH {

		numBytes, err = conn.Read(buffer)
		// ignore timeout errors if there is already banner content
		if err, ok := err.(net.Error); ok && err.Timeout() {
			if len(logStruct.Banner) == 0 {
				return err
			} else {
				break
			}
		}

		if err != nil && err != io.EOF {
			return err
		}

		if containsIAC(buffer) {
			continue
		}

		if count == rounds-1 {
			logStruct.Banner = logStruct.Banner + string(buffer[0:maxReadSize%READ_BUFFER_LENGTH])
		} else {
			logStruct.Banner = logStruct.Banner + string(buffer[0:numBytes])
		}
		count += 1
	}

	return nil
}

func NegotiateOptions(logStruct *TelnetLog, conn net.Conn) error {
	var readBuffer, retBuffer []byte
	var option, optionType, returnOptionType byte
	var iacIndex, firstUnreadIndex, numBytes, numDataBytes int
	var err error

	for finishedNegotiating := false; finishedNegotiating == false; {
		readBuffer = make([]byte, READ_BUFFER_LENGTH)
		retBuffer = nil
		numBytes, err = conn.Read(readBuffer)
		numDataBytes = numBytes

		if err != nil {
			return err
		}

		if numBytes == len(readBuffer) {
			return errors.New("Not enough buffer space for telnet options")
		}

		// Negotiate options

		for iacIndex = bytes.IndexByte(readBuffer, IAC); iacIndex != -1; iacIndex = bytes.IndexByte(readBuffer, IAC) {
			firstUnreadIndex = 0
			optionType = readBuffer[iacIndex+1]
			option = readBuffer[iacIndex+2]

			// ignore go ahead
			if optionType == GO_AHEAD {
				readBuffer = readBuffer[0:iacIndex]
				numBytes = iacIndex
				firstUnreadIndex = 0
				break
			}

			// record all offered options
			if optionType == WILL || optionType == DO {
				logStruct.SupportedOpts = append(logStruct.SupportedOpts, fmt.Sprintf("%d", option))
			} else if optionType == WONT || optionType == DONT {
				logStruct.UnsupportedOpts = append(logStruct.UnsupportedOpts, fmt.Sprintf("%d", option))
			}

			// reject all offered options
			if optionType == WILL || optionType == WONT {
				returnOptionType = DONT
			} else if optionType == DO || optionType == DONT {
				returnOptionType = WONT
			} else {
				return errors.New("Unsupported telnet IAC option type" + fmt.Sprintf("%d", optionType))
			}

			retBuffer = append(retBuffer, IAC)
			retBuffer = append(retBuffer, returnOptionType)
			retBuffer = append(retBuffer, option)

			firstUnreadIndex = iacIndex + IAC_CMD_LENGTH
			numDataBytes -= firstUnreadIndex
			readBuffer = readBuffer[firstUnreadIndex:]
		}

		if _, err = conn.Write(retBuffer); err != nil {
			return err
		}

		numIACBytes := numBytes - numDataBytes
		finishedNegotiating = numBytes != numIACBytes
	}

	// no more IAC commands, just read the resulting data
	if numDataBytes >= 0 {
		logStruct.Banner = string(readBuffer[0:numBytes])
	}

	return nil
}

func containsIAC(buffer []byte) bool {
	return bytes.IndexByte(buffer, IAC) != -1
}
<|endoftext|>


<commit_before>package metadata

/*****************************************
 * This file was generated by SalsaFlow. *
 * Please do not modify it manually.     *
 *****************************************/

const Version = "0.7.0"
<commit_msg>Bump version to 0.8.0<commit_after>package metadata

/*****************************************
 * This file was generated by SalsaFlow. *
 * Please do not modify it manually.     *
 *****************************************/

const Version = "0.8.0"
<|endoftext|>


<commit_before>package amf

import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"testing"
	"time"
)

func EncodeAndDecode(val interface{}, ver Version) (result interface{}, err error) {
	enc := new(Encoder)
	dec := new(Decoder)

	buf := new(bytes.Buffer)

	_, err = enc.Encode(buf, val, ver)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("error in encode: %s", err))
	}

	result, err = dec.Decode(buf, ver)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("error in decode: %s", err))
	}

	return
}

func Compare(val interface{}, ver Version, name string, t *testing.T) {
	result, err := EncodeAndDecode(val, ver)
	if err != nil {
		t.Errorf("%s: %s", name, err)
	}

	if !reflect.DeepEqual(val, result) {
		val_v := reflect.ValueOf(val)
		result_v := reflect.ValueOf(result)

		t.Errorf("%s: comparison failed between %+v (%s) and %+v (%s)", name, val, val_v.Type(), result, result_v.Type())

		Dump("expected", val)
		Dump("got", result)
	}

	// if val != result {
	// 	t.Errorf("%s: comparison failed between %+v and %+v", name, val, result)
	// }
}

func TestAmf0Number(t *testing.T) {
	Compare(float64(3.14159), 0, "amf0 number float", t)
	Compare(float64(124567890), 0, "amf0 number high", t)
	Compare(float64(-34.2), 0, "amf0 number negative", t)
}

func TestAmf0String(t *testing.T) {
	Compare("a pup!", 0, "amf0 string simple", t)
	Compare("日本語", 0, "amf0 string utf8", t)
}

func TestAmf0Boolean(t *testing.T) {
	Compare(true, 0, "amf0 boolean true", t)
	Compare(false, 0, "amf0 boolean false", t)
}

func TestAmf0Null(t *testing.T) {
	Compare(nil, 0, "amf0 boolean nil", t)
}

func TestAmf0Object(t *testing.T) {
	obj := make(Object)
	obj["dog"] = "alfie"
	obj["coffee"] = true
	obj["drugs"] = false
	obj["pi"] = 3.14159

	res, err := EncodeAndDecode(obj, 0)
	if err != nil {
		t.Errorf("amf0 object: %s", err)
	}

	result, ok := res.(Object)
	if ok != true {
		t.Errorf("amf0 object conversion failed")
	}

	if result["dog"] != "alfie" {
		t.Errorf("amf0 object string: comparison failed")
	}

	if result["coffee"] != true {
		t.Errorf("amf0 object true: comparison failed")
	}

	if result["drugs"] != false {
		t.Errorf("amf0 object false: comparison failed")
	}

	if result["pi"] != float64(3.14159) {
		t.Errorf("amf0 object float: comparison failed")
	}
}

func TestAmf0Array(t *testing.T) {
	arr := [5]float64{1, 2, 3, 4, 5}

	res, err := EncodeAndDecode(arr, 0)
	if err != nil {
		t.Error("amf0 object: %s", err)
	}

	result, ok := res.(Array)
	if ok != true {
		t.Errorf("amf0 array conversion failed")
	}

	for i := 0; i < len(arr); i++ {
		if arr[i] != result[i] {
			t.Errorf("amf0 array %d comparison failed: %v / %v", i, arr[i], result[i])
		}
	}
}

func TestAmf3Integer(t *testing.T) {
	Compare(uint32(0), 3, "amf3 integer zero", t)
	Compare(uint32(1245), 3, "amf3 integer low", t)
	Compare(uint32(123456), 3, "amf3 integer high", t)
}

func TestAmf3Double(t *testing.T) {
	Compare(float64(3.14159), 3, "amf3 double float", t)
	Compare(float64(1234567890), 3, "amf3 double high", t)
	Compare(float64(-12345), 3, "amf3 double negative", t)
}

func TestAmf3String(t *testing.T) {
	Compare("a pup!", 0, "amf0 string simple", t)
	Compare("日本語", 0, "amf0 string utf8", t)
}

func TestAmf3Boolean(t *testing.T) {
	Compare(true, 3, "amf3 boolean true", t)
	Compare(false, 3, "amf3 boolean false", t)
}

func TestAmf3Null(t *testing.T) {
	Compare(nil, 3, "amf3 boolean nil", t)
}

func TestAmf3Date(t *testing.T) {
	t1 := time.Unix(time.Now().Unix(), 0) // nanoseconds discarded
	t2, _ := time.Parse(time.RFC822, "04 Sep 83 12:04 EST")

	Compare(t1, 3, "amf3 date now", t)
	Compare(t2, 3, "amf3 date earlier", t)
}

func TestAmf3Array(t *testing.T) {
	obj := make(Object)
	obj["key"] = "val"

	var arr Array
	arr = append(arr, "amf")
	arr = append(arr, float64(2))
	arr = append(arr, -34.95)
	arr = append(arr, true)
	arr = append(arr, false)

	res, err := EncodeAndDecode(arr, 3)
	if err != nil {
		t.Error("amf3 object: %s", err)
	}

	result, ok := res.(Array)
	if ok != true {
		t.Errorf("amf3 array conversion failed: %+v", res)
	}

	for i := 0; i < len(arr); i++ {
		if arr[i] != result[i] {
			t.Errorf("amf3 array %d comparison failed: %v / %v", i, arr[i], result[i])
		}
	}
}

func TestAmf3ByteArray(t *testing.T) {
	enc := new(Encoder)
	dec := new(Decoder)

	buf := new(bytes.Buffer)

	expect := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x00}

	enc.EncodeAmf3ByteArray(buf, expect, true)

	result, err := dec.DecodeAmf3ByteArray(buf, true)
	if err != nil {
		t.Errorf("err: %s", err)
	}

	if bytes.Compare(result, expect) != 0 {
		t.Errorf("expected: %+v, got %+v", expect, buf)
	}
}
<commit_msg>Fix time parse issue for earlier versions of go<commit_after>package amf

import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
	"testing"
	"time"
)

func EncodeAndDecode(val interface{}, ver Version) (result interface{}, err error) {
	enc := new(Encoder)
	dec := new(Decoder)

	buf := new(bytes.Buffer)

	_, err = enc.Encode(buf, val, ver)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("error in encode: %s", err))
	}

	result, err = dec.Decode(buf, ver)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("error in decode: %s", err))
	}

	return
}

func Compare(val interface{}, ver Version, name string, t *testing.T) {
	result, err := EncodeAndDecode(val, ver)
	if err != nil {
		t.Errorf("%s: %s", name, err)
	}

	if !reflect.DeepEqual(val, result) {
		val_v := reflect.ValueOf(val)
		result_v := reflect.ValueOf(result)

		t.Errorf("%s: comparison failed between %+v (%s) and %+v (%s)", name, val, val_v.Type(), result, result_v.Type())

		Dump("expected", val)
		Dump("got", result)
	}

	// if val != result {
	// 	t.Errorf("%s: comparison failed between %+v and %+v", name, val, result)
	// }
}

func TestAmf0Number(t *testing.T) {
	Compare(float64(3.14159), 0, "amf0 number float", t)
	Compare(float64(124567890), 0, "amf0 number high", t)
	Compare(float64(-34.2), 0, "amf0 number negative", t)
}

func TestAmf0String(t *testing.T) {
	Compare("a pup!", 0, "amf0 string simple", t)
	Compare("日本語", 0, "amf0 string utf8", t)
}

func TestAmf0Boolean(t *testing.T) {
	Compare(true, 0, "amf0 boolean true", t)
	Compare(false, 0, "amf0 boolean false", t)
}

func TestAmf0Null(t *testing.T) {
	Compare(nil, 0, "amf0 boolean nil", t)
}

func TestAmf0Object(t *testing.T) {
	obj := make(Object)
	obj["dog"] = "alfie"
	obj["coffee"] = true
	obj["drugs"] = false
	obj["pi"] = 3.14159

	res, err := EncodeAndDecode(obj, 0)
	if err != nil {
		t.Errorf("amf0 object: %s", err)
	}

	result, ok := res.(Object)
	if ok != true {
		t.Errorf("amf0 object conversion failed")
	}

	if result["dog"] != "alfie" {
		t.Errorf("amf0 object string: comparison failed")
	}

	if result["coffee"] != true {
		t.Errorf("amf0 object true: comparison failed")
	}

	if result["drugs"] != false {
		t.Errorf("amf0 object false: comparison failed")
	}

	if result["pi"] != float64(3.14159) {
		t.Errorf("amf0 object float: comparison failed")
	}
}

func TestAmf0Array(t *testing.T) {
	arr := [5]float64{1, 2, 3, 4, 5}

	res, err := EncodeAndDecode(arr, 0)
	if err != nil {
		t.Error("amf0 object: %s", err)
	}

	result, ok := res.(Array)
	if ok != true {
		t.Errorf("amf0 array conversion failed")
	}

	for i := 0; i < len(arr); i++ {
		if arr[i] != result[i] {
			t.Errorf("amf0 array %d comparison failed: %v / %v", i, arr[i], result[i])
		}
	}
}

func TestAmf3Integer(t *testing.T) {
	Compare(uint32(0), 3, "amf3 integer zero", t)
	Compare(uint32(1245), 3, "amf3 integer low", t)
	Compare(uint32(123456), 3, "amf3 integer high", t)
}

func TestAmf3Double(t *testing.T) {
	Compare(float64(3.14159), 3, "amf3 double float", t)
	Compare(float64(1234567890), 3, "amf3 double high", t)
	Compare(float64(-12345), 3, "amf3 double negative", t)
}

func TestAmf3String(t *testing.T) {
	Compare("a pup!", 0, "amf0 string simple", t)
	Compare("日本語", 0, "amf0 string utf8", t)
}

func TestAmf3Boolean(t *testing.T) {
	Compare(true, 3, "amf3 boolean true", t)
	Compare(false, 3, "amf3 boolean false", t)
}

func TestAmf3Null(t *testing.T) {
	Compare(nil, 3, "amf3 boolean nil", t)
}

func TestAmf3Date(t *testing.T) {
	t1 := time.Unix(time.Now().Unix(), 0) // nanoseconds discarded
	t2 := time.Date(1983, 9, 4, 12, 4, 8, 0, time.Local)

	Compare(t1, 3, "amf3 date now", t)
	Compare(t2, 3, "amf3 date earlier", t)
}

func TestAmf3Array(t *testing.T) {
	obj := make(Object)
	obj["key"] = "val"

	var arr Array
	arr = append(arr, "amf")
	arr = append(arr, float64(2))
	arr = append(arr, -34.95)
	arr = append(arr, true)
	arr = append(arr, false)

	res, err := EncodeAndDecode(arr, 3)
	if err != nil {
		t.Error("amf3 object: %s", err)
	}

	result, ok := res.(Array)
	if ok != true {
		t.Errorf("amf3 array conversion failed: %+v", res)
	}

	for i := 0; i < len(arr); i++ {
		if arr[i] != result[i] {
			t.Errorf("amf3 array %d comparison failed: %v / %v", i, arr[i], result[i])
		}
	}
}

func TestAmf3ByteArray(t *testing.T) {
	enc := new(Encoder)
	dec := new(Decoder)

	buf := new(bytes.Buffer)

	expect := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x00}

	enc.EncodeAmf3ByteArray(buf, expect, true)

	result, err := dec.DecodeAmf3ByteArray(buf, true)
	if err != nil {
		t.Errorf("err: %s", err)
	}

	if bytes.Compare(result, expect) != 0 {
		t.Errorf("expected: %+v, got %+v", expect, buf)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build !js

package ui

import (
	"errors"
	"runtime"
	"time"

	"github.com/go-gl/glfw/v3.1/glfw"
	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
)

func Now() int64 {
	return time.Now().UnixNano()
}

type UserInterface struct {
	window           *glfw.Window
	width            int
	height           int
	scale            int
	deviceScale      float64
	framebufferScale int
	context          *opengl.Context
	funcs            chan func()
}

var currentUI *UserInterface

func CurrentUI() *UserInterface {
	return currentUI
}

func Init() (*opengl.Context, error) {
	runtime.LockOSThread()

	err := glfw.Init()
	if err != nil {
		return nil, err
	}
	glfw.WindowHint(glfw.Visible, glfw.False)
	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 2)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)

	// As start, create an window with temporary size to create OpenGL context thread.
	window, err := glfw.CreateWindow(16, 16, "", nil, nil)
	if err != nil {
		return nil, err
	}

	u := &UserInterface{
		window: window,
		funcs:  make(chan func()),
	}
	ch := make(chan error)
	go func() {
		runtime.LockOSThread()
		u.window.MakeContextCurrent()
		glfw.SwapInterval(1)
		var err error
		u.context, err = opengl.NewContext()
		if err != nil {
			ch <- err
		}
		close(ch)
		u.context.Loop()
	}()
	currentUI = u
	if err := <-ch; err != nil {
		return nil, err
	}
	if err := u.context.Init(); err != nil {
		return nil, err
	}

	return u.context, nil
}

func Main() error {
	return CurrentUI().main()
}

func (u *UserInterface) main() error {
	// TODO: Check this is done on the main thread.
	for f := range u.funcs {
		f()
	}
	return nil
}

func (u *UserInterface) runOnMainThread(f func()) {
	if u.funcs == nil {
		// already closed
		return
	}
	ch := make(chan struct{})
	u.funcs <- func() {
		f()
		close(ch)
	}
	<-ch
}

func (u *UserInterface) SetScreenSize(width, height int) bool {
	r := false
	u.runOnMainThread(func() {
		r = u.setScreenSize(width, height, u.scale)
	})
	return r
}

func (u *UserInterface) SetScreenScale(scale int) bool {
	r := false
	u.runOnMainThread(func() {
		r = u.setScreenSize(u.width, u.height, scale)
	})
	return r
}

func (u *UserInterface) ScreenScale() int {
	s := 0
	u.runOnMainThread(func() {
		s = u.scale
	})
	return s
}

func (u *UserInterface) ActualScreenScale() int {
	s := 0
	u.runOnMainThread(func() {
		s = u.actualScreenScale()
	})
	return s
}

func (u *UserInterface) Start(width, height, scale int, title string) error {
	var ferr error
	u.runOnMainThread(func() {
		m := glfw.GetPrimaryMonitor()
		v := m.GetVideoMode()
		mw, _ := m.GetPhysicalSize()
		u.deviceScale = 1
		u.framebufferScale = 1
		// mw can be 0 on some environment like Linux VM
		if 0 < mw {
			dpi := float64(v.Width) * 25.4 / float64(mw)
			u.deviceScale = dpi / 96
			if u.deviceScale < 1 {
				u.deviceScale = 1
			}
		}

		if !u.setScreenSize(width, height, scale) {
			ferr = errors.New("ui: Fail to set the screen size")
			return
		}
		u.window.SetTitle(title)
		u.window.Show()

		x := (v.Width - width*u.windowScale()) / 2
		y := (v.Height - height*u.windowScale()) / 3
		u.window.SetPos(x, y)
	})
	return nil
}

func (u *UserInterface) windowScale() int {
	return u.scale * int(u.deviceScale)
}

func (u *UserInterface) actualScreenScale() int {
	return u.windowScale() * u.framebufferScale
}

func (u *UserInterface) pollEvents() error {
	glfw.PollEvents()
	return currentInput.update(u.window, u.windowScale())
}

func (u *UserInterface) DoEvents() error {
	var ferr error
	u.runOnMainThread(func() {
		if err := u.pollEvents(); err != nil {
			ferr = err
			return
		}
		for u.window.GetAttrib(glfw.Focused) == 0 {
			// Wait for an arbitrary period to avoid busy loop.
			time.Sleep(time.Second / 60)
			if err := u.pollEvents(); err != nil {
				ferr = err
				return
			}
			if u.window.ShouldClose() {
				return
			}
		}
	})
	return ferr
}

func (u *UserInterface) Terminate() {
	u.runOnMainThread(func() {
		glfw.Terminate()
	})
	close(u.funcs)
	u.funcs = nil
}

func (u *UserInterface) IsClosed() bool {
	r := false
	u.runOnMainThread(func() {
		r = u.window.ShouldClose()
	})
	return r
}

func (u *UserInterface) SwapBuffers() {
	u.runOnMainThread(func() {
		u.swapBuffers()
	})
}

func (u *UserInterface) swapBuffers() {
	// The bound framebuffer must be the default one (0) before swapping buffers.
	u.context.BindZeroFramebuffer()
	u.context.RunOnContextThread(func() {
		u.window.SwapBuffers()
	})
}

func (u *UserInterface) setScreenSize(width, height, scale int) bool {
	if u.width == width && u.height == height && u.scale == scale {
		return false
	}

	// u.scale should be set first since this affects windowScale().
	origScale := u.scale
	u.scale = scale

	// On Windows, giving a too small width doesn't call a callback (#165).
	// To prevent hanging up, return asap if the width is too small.
	// 252 is an arbitrary number and I guess this is small enough.
	const minWindowWidth = 252
	if width*u.actualScreenScale() < minWindowWidth {
		u.scale = origScale
		return false
	}
	u.width = width
	u.height = height

	// To make sure the current existing framebuffers are rendered,
	// swap buffers here before SetSize is called.
	u.swapBuffers()

	ch := make(chan struct{})
	window := u.window
	window.SetFramebufferSizeCallback(func(_ *glfw.Window, width, height int) {
		window.SetFramebufferSizeCallback(nil)
		close(ch)
	})
	window.SetSize(width*u.windowScale(), height*u.windowScale())

event:
	for {
		glfw.PollEvents()
		select {
		case <-ch:
			break event
		default:
		}
	}
	// This is usually 1, but sometimes more than 1 (e.g. Retina Mac)
	fw, _ := window.GetFramebufferSize()
	u.framebufferScale = fw / width / u.windowScale()
	return true
}
<commit_msg>ui: Refactoring<commit_after>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build !js

package ui

import (
	"errors"
	"runtime"
	"time"

	"github.com/go-gl/glfw/v3.1/glfw"
	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
)

func Now() int64 {
	return time.Now().UnixNano()
}

type UserInterface struct {
	window           *glfw.Window
	width            int
	height           int
	scale            int
	deviceScale      float64
	framebufferScale int
	context          *opengl.Context
	funcs            chan func()
}

var currentUI *UserInterface

func CurrentUI() *UserInterface {
	return currentUI
}

func Init() (*opengl.Context, error) {
	runtime.LockOSThread()

	if err := glfw.Init(); err != nil {
		return nil, err
	}
	glfw.WindowHint(glfw.Visible, glfw.False)
	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 2)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)

	// As start, create an window with temporary size to create OpenGL context thread.
	window, err := glfw.CreateWindow(16, 16, "", nil, nil)
	if err != nil {
		return nil, err
	}

	u := &UserInterface{
		window: window,
		funcs:  make(chan func()),
	}
	ch := make(chan error)
	go func() {
		runtime.LockOSThread()
		u.window.MakeContextCurrent()
		glfw.SwapInterval(1)
		var err error
		u.context, err = opengl.NewContext()
		if err != nil {
			ch <- err
		}
		close(ch)
		u.context.Loop()
	}()
	currentUI = u
	if err := <-ch; err != nil {
		return nil, err
	}
	if err := u.context.Init(); err != nil {
		return nil, err
	}

	return u.context, nil
}

func Main() error {
	return CurrentUI().main()
}

func (u *UserInterface) main() error {
	// TODO: Check this is done on the main thread.
	for f := range u.funcs {
		f()
	}
	return nil
}

func (u *UserInterface) runOnMainThread(f func()) {
	if u.funcs == nil {
		// already closed
		return
	}
	ch := make(chan struct{})
	u.funcs <- func() {
		f()
		close(ch)
	}
	<-ch
}

func (u *UserInterface) SetScreenSize(width, height int) bool {
	r := false
	u.runOnMainThread(func() {
		r = u.setScreenSize(width, height, u.scale)
	})
	return r
}

func (u *UserInterface) SetScreenScale(scale int) bool {
	r := false
	u.runOnMainThread(func() {
		r = u.setScreenSize(u.width, u.height, scale)
	})
	return r
}

func (u *UserInterface) ScreenScale() int {
	s := 0
	u.runOnMainThread(func() {
		s = u.scale
	})
	return s
}

func (u *UserInterface) ActualScreenScale() int {
	s := 0
	u.runOnMainThread(func() {
		s = u.actualScreenScale()
	})
	return s
}

func (u *UserInterface) Start(width, height, scale int, title string) error {
	var ferr error
	u.runOnMainThread(func() {
		m := glfw.GetPrimaryMonitor()
		v := m.GetVideoMode()
		mw, _ := m.GetPhysicalSize()
		u.deviceScale = 1
		u.framebufferScale = 1
		// mw can be 0 on some environment like Linux VM
		if 0 < mw {
			dpi := float64(v.Width) * 25.4 / float64(mw)
			u.deviceScale = dpi / 96
			if u.deviceScale < 1 {
				u.deviceScale = 1
			}
		}

		if !u.setScreenSize(width, height, scale) {
			ferr = errors.New("ui: Fail to set the screen size")
			return
		}
		u.window.SetTitle(title)
		u.window.Show()

		x := (v.Width - width*u.windowScale()) / 2
		y := (v.Height - height*u.windowScale()) / 3
		u.window.SetPos(x, y)
	})
	return nil
}

func (u *UserInterface) windowScale() int {
	return u.scale * int(u.deviceScale)
}

func (u *UserInterface) actualScreenScale() int {
	return u.windowScale() * u.framebufferScale
}

func (u *UserInterface) pollEvents() error {
	glfw.PollEvents()
	return currentInput.update(u.window, u.windowScale())
}

func (u *UserInterface) DoEvents() error {
	var ferr error
	u.runOnMainThread(func() {
		if err := u.pollEvents(); err != nil {
			ferr = err
			return
		}
		for u.window.GetAttrib(glfw.Focused) == 0 {
			// Wait for an arbitrary period to avoid busy loop.
			time.Sleep(time.Second / 60)
			if err := u.pollEvents(); err != nil {
				ferr = err
				return
			}
			if u.window.ShouldClose() {
				return
			}
		}
	})
	return ferr
}

func (u *UserInterface) Terminate() {
	u.runOnMainThread(func() {
		glfw.Terminate()
	})
	close(u.funcs)
	u.funcs = nil
}

func (u *UserInterface) IsClosed() bool {
	r := false
	u.runOnMainThread(func() {
		r = u.window.ShouldClose()
	})
	return r
}

func (u *UserInterface) SwapBuffers() {
	u.runOnMainThread(func() {
		u.swapBuffers()
	})
}

func (u *UserInterface) swapBuffers() {
	// The bound framebuffer must be the default one (0) before swapping buffers.
	u.context.BindZeroFramebuffer()
	u.context.RunOnContextThread(func() {
		u.window.SwapBuffers()
	})
}

func (u *UserInterface) setScreenSize(width, height, scale int) bool {
	if u.width == width && u.height == height && u.scale == scale {
		return false
	}

	// u.scale should be set first since this affects windowScale().
	origScale := u.scale
	u.scale = scale

	// On Windows, giving a too small width doesn't call a callback (#165).
	// To prevent hanging up, return asap if the width is too small.
	// 252 is an arbitrary number and I guess this is small enough.
	const minWindowWidth = 252
	if width*u.actualScreenScale() < minWindowWidth {
		u.scale = origScale
		return false
	}
	u.width = width
	u.height = height

	// To make sure the current existing framebuffers are rendered,
	// swap buffers here before SetSize is called.
	u.swapBuffers()

	ch := make(chan struct{})
	window := u.window
	window.SetFramebufferSizeCallback(func(_ *glfw.Window, width, height int) {
		window.SetFramebufferSizeCallback(nil)
		close(ch)
	})
	window.SetSize(width*u.windowScale(), height*u.windowScale())

event:
	for {
		glfw.PollEvents()
		select {
		case <-ch:
			break event
		default:
		}
	}
	// This is usually 1, but sometimes more than 1 (e.g. Retina Mac)
	fw, _ := window.GetFramebufferSize()
	u.framebufferScale = fw / width / u.windowScale()
	return true
}
<|endoftext|>