<commit_before>package daemon // import "github.com/docker/docker/daemon"

import (
	"fmt"
	"net/url"
	"os"
	"runtime"
	"strings"
	"time"

	"github.com/docker/docker/api"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/cli/debug"
	"github.com/docker/docker/daemon/logger"
	"github.com/docker/docker/dockerversion"
	"github.com/docker/docker/pkg/fileutils"
	"github.com/docker/docker/pkg/parsers/kernel"
	"github.com/docker/docker/pkg/parsers/operatingsystem"
	"github.com/docker/docker/pkg/platform"
	"github.com/docker/docker/pkg/sysinfo"
	"github.com/docker/docker/pkg/system"
	"github.com/docker/docker/registry"
	metrics "github.com/docker/go-metrics"
	"github.com/sirupsen/logrus"
)

// SystemInfo returns information about the host server the daemon is running on.
func (daemon *Daemon) SystemInfo() (*types.Info, error) {
	defer metrics.StartTimer(hostInfoFunctions.WithValues("system_info"))()

	sysInfo := sysinfo.New(true)
	cRunning, cPaused, cStopped := stateCtr.get()

	v := &types.Info{
		ID:                 daemon.ID,
		Containers:         cRunning + cPaused + cStopped,
		ContainersRunning:  cRunning,
		ContainersPaused:   cPaused,
		ContainersStopped:  cStopped,
		Images:             daemon.imageService.CountImages(),
		IPv4Forwarding:     !sysInfo.IPv4ForwardingDisabled,
		BridgeNfIptables:   !sysInfo.BridgeNFCallIPTablesDisabled,
		BridgeNfIP6tables:  !sysInfo.BridgeNFCallIP6TablesDisabled,
		Debug:              debug.IsEnabled(),
		Name:               hostName(),
		NFd:                fileutils.GetTotalUsedFds(),
		NGoroutines:        runtime.NumGoroutine(),
		SystemTime:         time.Now().Format(time.RFC3339Nano),
		LoggingDriver:      daemon.defaultLogConfig.Type,
		CgroupDriver:       daemon.getCgroupDriver(),
		NEventsListener:    daemon.EventsService.SubscribersCount(),
		KernelVersion:      kernelVersion(),
		OperatingSystem:    operatingSystem(),
		OSVersion:          osVersion(),
		IndexServerAddress: registry.IndexServer,
		OSType:             platform.OSType,
		Architecture:       platform.Architecture,
		RegistryConfig:     daemon.RegistryService.ServiceConfig(),
		NCPU:               sysinfo.NumCPU(),
		MemTotal:           memInfo().MemTotal,
		GenericResources:   daemon.genericResources,
		DockerRootDir:      daemon.configStore.Root,
		Labels:             daemon.configStore.Labels,
		ExperimentalBuild:  daemon.configStore.Experimental,
		ServerVersion:      dockerversion.Version,
		ClusterStore:       daemon.configStore.ClusterStore,
		ClusterAdvertise:   daemon.configStore.ClusterAdvertise,
		HTTPProxy:          maskCredentials(getEnvAny("HTTP_PROXY", "http_proxy")),
		HTTPSProxy:         maskCredentials(getEnvAny("HTTPS_PROXY", "https_proxy")),
		NoProxy:            getEnvAny("NO_PROXY", "no_proxy"),
		LiveRestoreEnabled: daemon.configStore.LiveRestoreEnabled,
		Isolation:          daemon.defaultIsolation,
	}

	daemon.fillAPIInfo(v)
	// Retrieve platform specific info
	daemon.fillPlatformInfo(v, sysInfo)
	daemon.fillDriverInfo(v)
	daemon.fillPluginsInfo(v)
	daemon.fillSecurityOptions(v, sysInfo)
	daemon.fillLicense(v)

	return v, nil
}

// SystemVersion returns version information about the daemon.
func (daemon *Daemon) SystemVersion() types.Version {
	defer metrics.StartTimer(hostInfoFunctions.WithValues("system_version"))()

	kernelVersion := kernelVersion()

	v := types.Version{
		Components: []types.ComponentVersion{
			{
				Name:    "Engine",
				Version: dockerversion.Version,
				Details: map[string]string{
					"GitCommit":     dockerversion.GitCommit,
					"ApiVersion":    api.DefaultVersion,
					"MinAPIVersion": api.MinVersion,
					"GoVersion":     runtime.Version(),
					"Os":            runtime.GOOS,
					"Arch":          runtime.GOARCH,
					"BuildTime":     dockerversion.BuildTime,
					"KernelVersion": kernelVersion,
					"Experimental":  fmt.Sprintf("%t", daemon.configStore.Experimental),
				},
			},
		},

		// Populate deprecated fields for older clients
		Version:       dockerversion.Version,
		GitCommit:     dockerversion.GitCommit,
		APIVersion:    api.DefaultVersion,
		MinAPIVersion: api.MinVersion,
		GoVersion:     runtime.Version(),
		Os:            runtime.GOOS,
		Arch:          runtime.GOARCH,
		BuildTime:     dockerversion.BuildTime,
		KernelVersion: kernelVersion,
		Experimental:  daemon.configStore.Experimental,
	}

	v.Platform.Name = dockerversion.PlatformName

	daemon.fillPlatformVersion(&v)
	return v
}

func (daemon *Daemon) fillDriverInfo(v *types.Info) {
	var ds [][2]string
	drivers := ""
	statuses := daemon.imageService.LayerStoreStatus()
	for os, gd := range daemon.graphDrivers {
		ds = append(ds, statuses[os]...)
		drivers += gd
		if len(daemon.graphDrivers) > 1 {
			drivers += fmt.Sprintf(" (%s) ", os)
		}
		switch gd {
		case "aufs", "devicemapper", "overlay":
			v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: the %s storage-driver is deprecated, and will be removed in a future release.", gd))
		}
	}
	drivers = strings.TrimSpace(drivers)

	v.Driver = drivers
	v.DriverStatus = ds

	fillDriverWarnings(v)
}

func (daemon *Daemon) fillPluginsInfo(v *types.Info) {
	v.Plugins = types.PluginsInfo{
		Volume:  daemon.volumes.GetDriverList(),
		Network: daemon.GetNetworkDriverList(),

		// The authorization plugins are returned in the order they are
		// used as they constitute a request/response modification chain.
		Authorization: daemon.configStore.AuthorizationPlugins,
		Log:           logger.ListDrivers(),
	}
}

func (daemon *Daemon) fillSecurityOptions(v *types.Info, sysInfo *sysinfo.SysInfo) {
	var securityOptions []string
	if sysInfo.AppArmor {
		securityOptions = append(securityOptions, "name=apparmor")
	}
	if sysInfo.Seccomp && supportsSeccomp {
		profile := daemon.seccompProfilePath
		if profile == "" {
			profile = "default"
		}
		securityOptions = append(securityOptions, fmt.Sprintf("name=seccomp,profile=%s", profile))
	}
	if selinuxEnabled() {
		securityOptions = append(securityOptions, "name=selinux")
	}
	if rootIDs := daemon.idMapping.RootPair(); rootIDs.UID != 0 || rootIDs.GID != 0 {
		securityOptions = append(securityOptions, "name=userns")
	}
	if daemon.Rootless() {
		securityOptions = append(securityOptions, "name=rootless")
	}
	if daemon.cgroupNamespacesEnabled(sysInfo) {
		securityOptions = append(securityOptions, "name=cgroupns")
	}

	v.SecurityOptions = securityOptions
}

func (daemon *Daemon) fillAPIInfo(v *types.Info) {
	const warn string = `
         Access to the remote API is equivalent to root access on the host. Refer
         to the 'Docker daemon attack surface' section in the documentation for
         more information: https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface`

	cfg := daemon.configStore
	for _, host := range cfg.Hosts {
		// cnf.Hosts is normalized during startup, so should always have a scheme/proto
		h := strings.SplitN(host, "://", 2)
		proto := h[0]
		addr := h[1]
		if proto != "tcp" {
			continue
		}
		if !cfg.TLS {
			v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: API is accessible on http://%s without encryption.%s", addr, warn))
			continue
		}
		if !cfg.TLSVerify {
			v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: API is accessible on https://%s without TLS client verification.%s", addr, warn))
			continue
		}
	}
}

func hostName() string {
	hostname := ""
	if hn, err := os.Hostname(); err != nil {
		logrus.Warnf("Could not get hostname: %v", err)
	} else {
		hostname = hn
	}
	return hostname
}

func kernelVersion() string {
	var kernelVersion string
	if kv, err := kernel.GetKernelVersion(); err != nil {
		logrus.Warnf("Could not get kernel version: %v", err)
	} else {
		kernelVersion = kv.String()
	}
	return kernelVersion
}

func memInfo() *system.MemInfo {
	memInfo, err := system.ReadMemInfo()
	if err != nil {
		logrus.Errorf("Could not read system memory info: %v", err)
		memInfo = &system.MemInfo{}
	}
	return memInfo
}

func operatingSystem() (operatingSystem string) {
	defer metrics.StartTimer(hostInfoFunctions.WithValues("operating_system"))()

	if s, err := operatingsystem.GetOperatingSystem(); err != nil {
		logrus.Warnf("Could not get operating system name: %v", err)
	} else {
		operatingSystem = s
	}
	// Don't do containerized check on Windows
	if runtime.GOOS != "windows" {
		if inContainer, err := operatingsystem.IsContainerized(); err != nil {
			logrus.Errorf("Could not determine if daemon is containerized: %v", err)
			operatingSystem += " (error determining if containerized)"
		} else if inContainer {
			operatingSystem += " (containerized)"
		}
	}

	return operatingSystem
}

func osVersion() (version string) {
	defer metrics.StartTimer(hostInfoFunctions.WithValues("os_version"))()

	version, err := operatingsystem.GetOperatingSystemVersion()
	if err != nil {
		logrus.Warnf("Could not get operating system version: %v", err)
	}

	return version
}

func maskCredentials(rawURL string) string {
	parsedURL, err := url.Parse(rawURL)
	if err != nil || parsedURL.User == nil {
		return rawURL
	}
	parsedURL.User = url.UserPassword("xxxxx", "xxxxx")
	maskedURL := parsedURL.String()
	return maskedURL
}

func getEnvAny(names ...string) string {
	for _, n := range names {
		if val := os.Getenv(n); val != "" {
			return val
		}
	}
	return ""
}
<commit_msg>Add warning about deprecated "cluster" options to "docker info"<commit_after>package daemon // import "github.com/docker/docker/daemon"

import (
	"fmt"
	"net/url"
	"os"
	"runtime"
	"strings"
	"time"

	"github.com/docker/docker/api"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/cli/debug"
	"github.com/docker/docker/daemon/logger"
	"github.com/docker/docker/dockerversion"
	"github.com/docker/docker/pkg/fileutils"
	"github.com/docker/docker/pkg/parsers/kernel"
	"github.com/docker/docker/pkg/parsers/operatingsystem"
	"github.com/docker/docker/pkg/platform"
	"github.com/docker/docker/pkg/sysinfo"
	"github.com/docker/docker/pkg/system"
	"github.com/docker/docker/registry"
	metrics "github.com/docker/go-metrics"
	"github.com/sirupsen/logrus"
)

// SystemInfo returns information about the host server the daemon is running on.
func (daemon *Daemon) SystemInfo() (*types.Info, error) {
	defer metrics.StartTimer(hostInfoFunctions.WithValues("system_info"))()

	sysInfo := sysinfo.New(true)
	cRunning, cPaused, cStopped := stateCtr.get()

	v := &types.Info{
		ID:                 daemon.ID,
		Containers:         cRunning + cPaused + cStopped,
		ContainersRunning:  cRunning,
		ContainersPaused:   cPaused,
		ContainersStopped:  cStopped,
		Images:             daemon.imageService.CountImages(),
		IPv4Forwarding:     !sysInfo.IPv4ForwardingDisabled,
		BridgeNfIptables:   !sysInfo.BridgeNFCallIPTablesDisabled,
		BridgeNfIP6tables:  !sysInfo.BridgeNFCallIP6TablesDisabled,
		Debug:              debug.IsEnabled(),
		Name:               hostName(),
		NFd:                fileutils.GetTotalUsedFds(),
		NGoroutines:        runtime.NumGoroutine(),
		SystemTime:         time.Now().Format(time.RFC3339Nano),
		LoggingDriver:      daemon.defaultLogConfig.Type,
		CgroupDriver:       daemon.getCgroupDriver(),
		NEventsListener:    daemon.EventsService.SubscribersCount(),
		KernelVersion:      kernelVersion(),
		OperatingSystem:    operatingSystem(),
		OSVersion:          osVersion(),
		IndexServerAddress: registry.IndexServer,
		OSType:             platform.OSType,
		Architecture:       platform.Architecture,
		RegistryConfig:     daemon.RegistryService.ServiceConfig(),
		NCPU:               sysinfo.NumCPU(),
		MemTotal:           memInfo().MemTotal,
		GenericResources:   daemon.genericResources,
		DockerRootDir:      daemon.configStore.Root,
		Labels:             daemon.configStore.Labels,
		ExperimentalBuild:  daemon.configStore.Experimental,
		ServerVersion:      dockerversion.Version,
		HTTPProxy:          maskCredentials(getEnvAny("HTTP_PROXY", "http_proxy")),
		HTTPSProxy:         maskCredentials(getEnvAny("HTTPS_PROXY", "https_proxy")),
		NoProxy:            getEnvAny("NO_PROXY", "no_proxy"),
		LiveRestoreEnabled: daemon.configStore.LiveRestoreEnabled,
		Isolation:          daemon.defaultIsolation,
	}

	daemon.fillClusterInfo(v)
	daemon.fillAPIInfo(v)
	// Retrieve platform specific info
	daemon.fillPlatformInfo(v, sysInfo)
	daemon.fillDriverInfo(v)
	daemon.fillPluginsInfo(v)
	daemon.fillSecurityOptions(v, sysInfo)
	daemon.fillLicense(v)

	return v, nil
}

// SystemVersion returns version information about the daemon.
func (daemon *Daemon) SystemVersion() types.Version {
	defer metrics.StartTimer(hostInfoFunctions.WithValues("system_version"))()

	kernelVersion := kernelVersion()

	v := types.Version{
		Components: []types.ComponentVersion{
			{
				Name:    "Engine",
				Version: dockerversion.Version,
				Details: map[string]string{
					"GitCommit":     dockerversion.GitCommit,
					"ApiVersion":    api.DefaultVersion,
					"MinAPIVersion": api.MinVersion,
					"GoVersion":     runtime.Version(),
					"Os":            runtime.GOOS,
					"Arch":          runtime.GOARCH,
					"BuildTime":     dockerversion.BuildTime,
					"KernelVersion": kernelVersion,
					"Experimental":  fmt.Sprintf("%t", daemon.configStore.Experimental),
				},
			},
		},

		// Populate deprecated fields for older clients
		Version:       dockerversion.Version,
		GitCommit:     dockerversion.GitCommit,
		APIVersion:    api.DefaultVersion,
		MinAPIVersion: api.MinVersion,
		GoVersion:     runtime.Version(),
		Os:            runtime.GOOS,
		Arch:          runtime.GOARCH,
		BuildTime:     dockerversion.BuildTime,
		KernelVersion: kernelVersion,
		Experimental:  daemon.configStore.Experimental,
	}

	v.Platform.Name = dockerversion.PlatformName

	daemon.fillPlatformVersion(&v)
	return v
}

func (daemon *Daemon) fillClusterInfo(v *types.Info) {
	v.ClusterAdvertise = daemon.configStore.ClusterAdvertise
	v.ClusterStore = daemon.configStore.ClusterStore

	if v.ClusterAdvertise != "" || v.ClusterStore != "" {
		v.Warnings = append(v.Warnings, `WARNING: node discovery and overlay networks with an external k/v store (cluster-advertise,
         cluster-store, cluster-store-opt) are deprecated and will be removed in a future release.`)
	}
}

func (daemon *Daemon) fillDriverInfo(v *types.Info) {
	var ds [][2]string
	drivers := ""
	statuses := daemon.imageService.LayerStoreStatus()
	for os, gd := range daemon.graphDrivers {
		ds = append(ds, statuses[os]...)
		drivers += gd
		if len(daemon.graphDrivers) > 1 {
			drivers += fmt.Sprintf(" (%s) ", os)
		}
		switch gd {
		case "aufs", "devicemapper", "overlay":
			v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: the %s storage-driver is deprecated, and will be removed in a future release.", gd))
		}
	}
	drivers = strings.TrimSpace(drivers)

	v.Driver = drivers
	v.DriverStatus = ds

	fillDriverWarnings(v)
}

func (daemon *Daemon) fillPluginsInfo(v *types.Info) {
	v.Plugins = types.PluginsInfo{
		Volume:  daemon.volumes.GetDriverList(),
		Network: daemon.GetNetworkDriverList(),

		// The authorization plugins are returned in the order they are
		// used as they constitute a request/response modification chain.
		Authorization: daemon.configStore.AuthorizationPlugins,
		Log:           logger.ListDrivers(),
	}
}

func (daemon *Daemon) fillSecurityOptions(v *types.Info, sysInfo *sysinfo.SysInfo) {
	var securityOptions []string
	if sysInfo.AppArmor {
		securityOptions = append(securityOptions, "name=apparmor")
	}
	if sysInfo.Seccomp && supportsSeccomp {
		profile := daemon.seccompProfilePath
		if profile == "" {
			profile = "default"
		}
		securityOptions = append(securityOptions, fmt.Sprintf("name=seccomp,profile=%s", profile))
	}
	if selinuxEnabled() {
		securityOptions = append(securityOptions, "name=selinux")
	}
	if rootIDs := daemon.idMapping.RootPair(); rootIDs.UID != 0 || rootIDs.GID != 0 {
		securityOptions = append(securityOptions, "name=userns")
	}
	if daemon.Rootless() {
		securityOptions = append(securityOptions, "name=rootless")
	}
	if daemon.cgroupNamespacesEnabled(sysInfo) {
		securityOptions = append(securityOptions, "name=cgroupns")
	}

	v.SecurityOptions = securityOptions
}

func (daemon *Daemon) fillAPIInfo(v *types.Info) {
	const warn string = `
         Access to the remote API is equivalent to root access on the host. Refer
         to the 'Docker daemon attack surface' section in the documentation for
         more information: https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface`

	cfg := daemon.configStore
	for _, host := range cfg.Hosts {
		// cnf.Hosts is normalized during startup, so should always have a scheme/proto
		h := strings.SplitN(host, "://", 2)
		proto := h[0]
		addr := h[1]
		if proto != "tcp" {
			continue
		}
		if !cfg.TLS {
			v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: API is accessible on http://%s without encryption.%s", addr, warn))
			continue
		}
		if !cfg.TLSVerify {
			v.Warnings = append(v.Warnings, fmt.Sprintf("WARNING: API is accessible on https://%s without TLS client verification.%s", addr, warn))
			continue
		}
	}
}

func hostName() string {
	hostname := ""
	if hn, err := os.Hostname(); err != nil {
		logrus.Warnf("Could not get hostname: %v", err)
	} else {
		hostname = hn
	}
	return hostname
}

func kernelVersion() string {
	var kernelVersion string
	if kv, err := kernel.GetKernelVersion(); err != nil {
		logrus.Warnf("Could not get kernel version: %v", err)
	} else {
		kernelVersion = kv.String()
	}
	return kernelVersion
}

func memInfo() *system.MemInfo {
	memInfo, err := system.ReadMemInfo()
	if err != nil {
		logrus.Errorf("Could not read system memory info: %v", err)
		memInfo = &system.MemInfo{}
	}
	return memInfo
}

func operatingSystem() (operatingSystem string) {
	defer metrics.StartTimer(hostInfoFunctions.WithValues("operating_system"))()

	if s, err := operatingsystem.GetOperatingSystem(); err != nil {
		logrus.Warnf("Could not get operating system name: %v", err)
	} else {
		operatingSystem = s
	}
	// Don't do containerized check on Windows
	if runtime.GOOS != "windows" {
		if inContainer, err := operatingsystem.IsContainerized(); err != nil {
			logrus.Errorf("Could not determine if daemon is containerized: %v", err)
			operatingSystem += " (error determining if containerized)"
		} else if inContainer {
			operatingSystem += " (containerized)"
		}
	}

	return operatingSystem
}

func osVersion() (version string) {
	defer metrics.StartTimer(hostInfoFunctions.WithValues("os_version"))()

	version, err := operatingsystem.GetOperatingSystemVersion()
	if err != nil {
		logrus.Warnf("Could not get operating system version: %v", err)
	}

	return version
}

func maskCredentials(rawURL string) string {
	parsedURL, err := url.Parse(rawURL)
	if err != nil || parsedURL.User == nil {
		return rawURL
	}
	parsedURL.User = url.UserPassword("xxxxx", "xxxxx")
	maskedURL := parsedURL.String()
	return maskedURL
}

func getEnvAny(names ...string) string {
	for _, n := range names {
		if val := os.Getenv(n); val != "" {
			return val
		}
	}
	return ""
}
<|endoftext|>


<commit_before>package apiserver

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"strings"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/net"
	"k8s.io/client-go/rest"

	exutil "github.com/openshift/origin/test/extended/util"
)

var _ = g.Describe("[sig-api-machinery][Feature:APIServer]", func() {
	defer g.GinkgoRecover()

	oc := exutil.NewCLI("apiserver")

	g.It("anonymous browsers should get a 403 from /", func() {
		transport, err := anonymousHttpTransport(oc.AdminConfig())
		o.Expect(err).NotTo(o.HaveOccurred())

		cv, err := oc.AdminConfigClient().ConfigV1().ClusterVersions().Get(context.TODO(), "version", metav1.GetOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		// For more info, refer to release notes of https://bugzilla.redhat.com/show_bug.cgi?id=1821771
		for _, history := range cv.Status.History {
			if strings.HasPrefix(history.Version, "4.1.") {
				g.Skip("the test is not expected to work with clusters upgraded from 4.1.x")
			}
		}

		req, err := http.NewRequest("GET", oc.AdminConfig().Host, nil)
		req.Header.Set("Accept", "*/*")
		resp, err := transport.RoundTrip(req)
		o.Expect(err).NotTo(o.HaveOccurred())

		o.Expect(resp.StatusCode).Should(o.Equal(http.StatusForbidden))
	})

	g.It("authenticated browser should get a 200 from /", func() {
		transport, err := rest.TransportFor(oc.AdminConfig())
		o.Expect(err).NotTo(o.HaveOccurred())

		req, err := http.NewRequest("GET", oc.AdminConfig().Host, nil)
		req.Header.Set("Accept", "*/*")
		resp, err := transport.RoundTrip(req)
		o.Expect(err).NotTo(o.HaveOccurred())

		o.Expect(resp.StatusCode).Should(o.Equal(http.StatusOK))

		o.Expect(resp.Header.Get("Content-Type")).Should(o.Equal("application/json"))
		type result struct {
			Paths []string
		}
		body, err := ioutil.ReadAll(resp.Body)
		o.Expect(err).NotTo(o.HaveOccurred())

		var got result
		err = json.Unmarshal(body, &got)
		o.Expect(err).NotTo(o.HaveOccurred())
	})
})

func anonymousHttpTransport(restConfig *rest.Config) (*http.Transport, error) {
	if len(restConfig.TLSClientConfig.CAData) == 0 {
		return &http.Transport{}, nil
	}
	pool := x509.NewCertPool()
	if ok := pool.AppendCertsFromPEM(restConfig.TLSClientConfig.CAData); !ok {
		return nil, errors.New("failed to add server CA certificates to client pool")
	}
	return net.SetTransportDefaults(&http.Transport{
		TLSClientConfig: &tls.Config{
			// only use RootCAs from client config, especially no client certs
			RootCAs: pool,
		},
	}), nil
}
<commit_msg>sig-api-machinery: remove project from authenticated browser APIServer tests<commit_after>package apiserver

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"strings"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/net"
	"k8s.io/client-go/rest"

	exutil "github.com/openshift/origin/test/extended/util"
)

var _ = g.Describe("[sig-api-machinery][Feature:APIServer]", func() {
	defer g.GinkgoRecover()

	oc := exutil.NewCLIWithoutNamespace("apiserver")

	g.It("anonymous browsers should get a 403 from /", func() {
		transport, err := anonymousHttpTransport(oc.AdminConfig())
		o.Expect(err).NotTo(o.HaveOccurred())

		cv, err := oc.AdminConfigClient().ConfigV1().ClusterVersions().Get(context.TODO(), "version", metav1.GetOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		// For more info, refer to release notes of https://bugzilla.redhat.com/show_bug.cgi?id=1821771
		for _, history := range cv.Status.History {
			if strings.HasPrefix(history.Version, "4.1.") {
				g.Skip("the test is not expected to work with clusters upgraded from 4.1.x")
			}
		}

		req, err := http.NewRequest("GET", oc.AdminConfig().Host, nil)
		req.Header.Set("Accept", "*/*")
		resp, err := transport.RoundTrip(req)
		o.Expect(err).NotTo(o.HaveOccurred())

		o.Expect(resp.StatusCode).Should(o.Equal(http.StatusForbidden))
	})

	g.It("authenticated browser should get a 200 from /", func() {
		transport, err := rest.TransportFor(oc.AdminConfig())
		o.Expect(err).NotTo(o.HaveOccurred())

		req, err := http.NewRequest("GET", oc.AdminConfig().Host, nil)
		req.Header.Set("Accept", "*/*")
		resp, err := transport.RoundTrip(req)
		o.Expect(err).NotTo(o.HaveOccurred())

		o.Expect(resp.StatusCode).Should(o.Equal(http.StatusOK))

		o.Expect(resp.Header.Get("Content-Type")).Should(o.Equal("application/json"))
		type result struct {
			Paths []string
		}
		body, err := ioutil.ReadAll(resp.Body)
		o.Expect(err).NotTo(o.HaveOccurred())

		var got result
		err = json.Unmarshal(body, &got)
		o.Expect(err).NotTo(o.HaveOccurred())
	})
})

func anonymousHttpTransport(restConfig *rest.Config) (*http.Transport, error) {
	if len(restConfig.TLSClientConfig.CAData) == 0 {
		return &http.Transport{}, nil
	}
	pool := x509.NewCertPool()
	if ok := pool.AppendCertsFromPEM(restConfig.TLSClientConfig.CAData); !ok {
		return nil, errors.New("failed to add server CA certificates to client pool")
	}
	return net.SetTransportDefaults(&http.Transport{
		TLSClientConfig: &tls.Config{
			// only use RootCAs from client config, especially no client certs
			RootCAs: pool,
		},
	}), nil
}
<|endoftext|>


<commit_before>package cachetree

import (
	"bytes"
	"encoding/binary"
	"io"
	"net"
)

func AskFileFromMembers(filename string) (data []byte) {
	conns := make(map[string]*net.TCPConn)
	for k, v :=range clientConnections {
		conns[k] = v
	}

	var err error
	for host, conn := range conns {
		err = requestFile(conn, filename)
		if err != nil {
			closeConn(host)
			go HandleMemberConnectionFail(err, host)
			continue
		}

		data, err = readFileIfExists(conn, filename)
		if err != nil {
			closeConn(host)
			go HandleMemberConnectionFail(err, host)
			continue
		}

		if data != nil {
			break
		}
	}

	return data
}

func DeleteFileFromMembers(filename string) {
	conns := make(map[string]*net.TCPConn)
	for k, v :=range clientConnections {
		conns[k] = v
	}

	for host, conn := range conns {
		err := requestFileDelete(conn, filename)
		if err != nil {
			closeConn(host)
			go HandleMemberConnectionFail(err, host)
			continue
		}

		file_name_data, err := readData(conn)
		if err != nil ||
			// Got wrong API
			string(file_name_data) != filename {
			closeConn(host)
			go HandleMemberConnectionFail(err, host)
			continue
		}
	}
}

func requestFile(conn *net.TCPConn, filename string) error {
	filename_len_bytes := make([]byte, 4)
	filename_bytes := []byte(filename)
	binary.BigEndian.PutUint32(filename_len_bytes, uint32(len(filename_bytes)))

	send_bytes := bytes.NewBuffer([]byte{})
	send_bytes.Write([]byte{CMD_REQUEST_FILE})
	send_bytes.Write(filename_len_bytes)
	send_bytes.Write(filename_bytes)

	_, err := io.Copy(conn, send_bytes)
	return err
}

func requestFileDelete(conn *net.TCPConn, filename string) error {
	filename_len_bytes := make([]byte, 4)
	filename_bytes := []byte(filename)
	binary.BigEndian.PutUint32(filename_len_bytes, uint32(len(filename_bytes)))

	send_bytes := bytes.NewBuffer([]byte{})
	send_bytes.Write([]byte{CMD_DELETE_FILE})
	send_bytes.Write(filename_len_bytes)
	send_bytes.Write(filename_bytes)

	_, err := io.Copy(conn, send_bytes)
	return err
}

func readFileIfExists(conn *net.TCPConn, filename string) ([]byte, error) {
	data, err := readData(conn)
	if err != nil {
		return nil, err
	}

	// if data length is 1, then this means connection don't have requested cache file
	if len(data) == 1 {
		return nil, nil
	}

	return data, nil
}
<commit_msg>fixed map copy bug<commit_after>package cachetree

import (
	"bytes"
	"encoding/binary"
	"io"
	"net"
)

func AskFileFromMembers(filename string) (data []byte) {
	conns := make(map[string]*net.TCPConn)
	for k, v := range clientConnections {
		conns[k] = v
	}

	var err error
	for host, conn := range conns {
		err = requestFile(conn, filename)
		if err != nil {
			closeConn(host)
			go HandleMemberConnectionFail(err, host)
			continue
		}

		data, err = readFileIfExists(conn, filename)
		if err != nil {
			closeConn(host)
			go HandleMemberConnectionFail(err, host)
			continue
		}

		if data != nil {
			break
		}
	}

	return data
}

func DeleteFileFromMembers(filename string) {
	conns := make(map[string]*net.TCPConn)
	for k, v := range clientConnections {
		conns[k] = v
	}

	for host, conn := range conns {
		err := requestFileDelete(conn, filename)
		if err != nil {
			closeConn(host)
			go HandleMemberConnectionFail(err, host)
			continue
		}

		file_name_data, err := readData(conn)
		if err != nil ||
			// Got wrong API
			string(file_name_data) != filename {
			closeConn(host)
			go HandleMemberConnectionFail(err, host)
			continue
		}
	}
}

func requestFile(conn *net.TCPConn, filename string) error {
	filename_len_bytes := make([]byte, 4)
	filename_bytes := []byte(filename)
	binary.BigEndian.PutUint32(filename_len_bytes, uint32(len(filename_bytes)))

	send_bytes := bytes.NewBuffer([]byte{})
	send_bytes.Write([]byte{CMD_REQUEST_FILE})
	send_bytes.Write(filename_len_bytes)
	send_bytes.Write(filename_bytes)

	_, err := io.Copy(conn, send_bytes)
	return err
}

func requestFileDelete(conn *net.TCPConn, filename string) error {
	filename_len_bytes := make([]byte, 4)
	filename_bytes := []byte(filename)
	binary.BigEndian.PutUint32(filename_len_bytes, uint32(len(filename_bytes)))

	send_bytes := bytes.NewBuffer([]byte{})
	send_bytes.Write([]byte{CMD_DELETE_FILE})
	send_bytes.Write(filename_len_bytes)
	send_bytes.Write(filename_bytes)

	_, err := io.Copy(conn, send_bytes)
	return err
}

func readFileIfExists(conn *net.TCPConn, filename string) ([]byte, error) {
	data, err := readData(conn)
	if err != nil {
		return nil, err
	}

	// if data length is 1, then this means connection don't have requested cache file
	if len(data) == 1 {
		return nil, nil
	}

	return data, nil
}
<|endoftext|>


<commit_before>package actions_on_google_golang

import "time"

type Iso8601Time struct {
	time.Time
}

const iso8601Layout = "2006-01-02T15:04:05-0700"

type ApiAiRequest struct {
	ID        string    `json:"id"`
	Timestamp time.Time `json:"timestamp"`
	Result    struct {
		Source           string `json:"source"`
		ResolvedQuery    string `json:"resolvedQuery"`
		Speech           string `json:"speech"`
		Action           string `json:"action"`
		ActionIncomplete bool   `json:"actionIncomplete"`
		Parameters       struct {
		} `json:"parameters"`
		Contexts []interface{} `json:"contexts"`
		Metadata struct {
			IntentID                  string `json:"intentId"`
			WebhookUsed               string `json:"webhookUsed"`
			WebhookForSlotFillingUsed string `json:"webhookForSlotFillingUsed"`
			IntentName                string `json:"intentName"`
		} `json:"metadata"`
		Fulfillment struct {
			Speech   string `json:"speech"`
			Messages []struct {
				Type   int    `json:"type"`
				Speech string `json:"speech"`
			} `json:"messages"`
		} `json:"fulfillment"`
		Score float64 `json:"score"`
	} `json:"result"`
	Status struct {
		Code      int    `json:"code"`
		ErrorType string `json:"errorType"`
	} `json:"status"`
	SessionID       string `json:"sessionId"`
	OriginalRequest struct {
		Source string `json:"source"`
		Data   struct {
			Inputs []struct {
				Arguments []struct {
					RawText   string `json:"raw_text"`
					TextValue string `json:"text_value"`
					Name      string `json:"name"`
				} `json:"arguments"`
				Intent    string `json:"intent"`
				RawInputs []struct {
					Query     string `json:"query"`
					InputType int    `json:"input_type"`
				} `json:"raw_inputs"`
			} `json:"inputs"`
			User struct {
				UserID string `json:"user_id"`
			} `json:"user"`
			Conversation struct {
				ConversationToken string `json:"conversation_token"`
				ConversationID    string `json:"conversation_id"`
				Type              int    `json:"type"`
			} `json:"conversation"`
		} `json:"data"`
	} `json:"originalRequest"`
}
<commit_msg>Add marshalling funcs<commit_after>package actions_on_google_golang

import "time"

type Iso8601Time struct {
	time.Time
}

const iso8601Layout = "2006-01-02T15:04:05-0700"

func (isoTime *Iso8601Time) Unmarshall(b []byte) (err error) {
	return
}

func (isoTime *Iso8601Time) Marshall() ([]byte, error) {
	return
}

type ApiAiRequest struct {
	ID        string    `json:"id"`
	Timestamp time.Time `json:"timestamp"`
	Result    struct {
		Source           string `json:"source"`
		ResolvedQuery    string `json:"resolvedQuery"`
		Speech           string `json:"speech"`
		Action           string `json:"action"`
		ActionIncomplete bool   `json:"actionIncomplete"`
		Parameters       struct {
		} `json:"parameters"`
		Contexts []interface{} `json:"contexts"`
		Metadata struct {
			IntentID                  string `json:"intentId"`
			WebhookUsed               string `json:"webhookUsed"`
			WebhookForSlotFillingUsed string `json:"webhookForSlotFillingUsed"`
			IntentName                string `json:"intentName"`
		} `json:"metadata"`
		Fulfillment struct {
			Speech   string `json:"speech"`
			Messages []struct {
				Type   int    `json:"type"`
				Speech string `json:"speech"`
			} `json:"messages"`
		} `json:"fulfillment"`
		Score float64 `json:"score"`
	} `json:"result"`
	Status struct {
		Code      int    `json:"code"`
		ErrorType string `json:"errorType"`
	} `json:"status"`
	SessionID       string `json:"sessionId"`
	OriginalRequest struct {
		Source string `json:"source"`
		Data   struct {
			Inputs []struct {
				Arguments []struct {
					RawText   string `json:"raw_text"`
					TextValue string `json:"text_value"`
					Name      string `json:"name"`
				} `json:"arguments"`
				Intent    string `json:"intent"`
				RawInputs []struct {
					Query     string `json:"query"`
					InputType int    `json:"input_type"`
				} `json:"raw_inputs"`
			} `json:"inputs"`
			User struct {
				UserID string `json:"user_id"`
			} `json:"user"`
			Conversation struct {
				ConversationToken string `json:"conversation_token"`
				ConversationID    string `json:"conversation_id"`
				Type              int    `json:"type"`
			} `json:"conversation"`
		} `json:"data"`
	} `json:"originalRequest"`
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package tally

// Version is the current version of the library.
const Version = "4.0.0-dev"
<commit_msg>Prepare release v4.0.0<commit_after>// Copyright (c) 2021 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package tally

// Version is the current version of the library.
const Version = "4.0.0"
<|endoftext|>


<commit_before>package storm

// Version of Storm
const Version = "1.0.0"
<commit_msg>Bump to v2.0.0-DEV<commit_after>package storm

// Version of Storm
const Version = "2.0.0-DEV"
<|endoftext|>


<commit_before>package main

/*
Given a version number MAJOR.MINOR.PATCH, increment the:

MAJOR version when you make incompatible API changes,
MINOR version when you add functionality in a backwards-compatible manner, and
PATCH version when you make backwards-compatible bug fixes.
*/
const VersionMajor = 4
const VersionMinor = 7
const VersionPatch = 0
<commit_msg>Bump to 4.9<commit_after>package main

/*
Given a version number MAJOR.MINOR.PATCH, increment the:

MAJOR version when you make incompatible API changes,
MINOR version when you add functionality in a backwards-compatible manner, and
PATCH version when you make backwards-compatible bug fixes.
*/
const VersionMajor = 4
const VersionMinor = 9
const VersionPatch = 0
<|endoftext|>


<commit_before>package main

const Version = "2.0.0"
<commit_msg>Bump to 2.0.1 for meshing changes<commit_after>package main

const Version = "2.0.1"
<|endoftext|>


<commit_before>// Copyright 2015 YP LLC.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package main

const VERSION = "0.1.9"
<commit_msg>Bump version to 0.1.9.1 -- keeping in mind this fork is out of date<commit_after>// Copyright 2015 YP LLC.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package main

const VERSION = "0.1.9.1"
<|endoftext|>


<commit_before>package here

// Version of here
const Version = "v0.1.5"
<commit_msg>version bump: v0.2.0<commit_after>package here

// Version of here
const Version = "v0.2.0"
<|endoftext|>


<commit_before>package shared

import (
	"fmt"
	"log"
)

/*
Version implements a vector clock.
*/
type Version map[string]int

/*
Increase the version for the given peer based on the already existing versions.
*/
func (v Version) Increase(selfid string) {
	/*TODO catch overflow on version increase!*/
	v[selfid] = v.Max() + 1
}

/*
Max version number from all listed peers.
*/
func (v Version) Max() int {
	var max int
	for _, value := range v {
		if value >= max {
			max = value
		}
	}
	return max
}

/*
Valid checks whether the version can be automerged or whether manual resolution
is required.
*/
func (v Version) Valid(that Version, selfid string) (Version, bool) {
	if v.Max() > that.Max() {
		// local version is ahead
		log.Println("Local version is ahead of remote version!")
		return v, false
	}
	// if local changes don't even exist no need to check the following
	_, ok := v[selfid]
	if ok && v[selfid] != that[selfid] {
		// this means local version was changed without the other peer realizing
		log.Println("Merge conflict! Local file has since changed.")
		return v, false
	}
	// otherwise we can update
	return that, true
}

/*
String representation of version.
*/
func (v Version) String() string {
	var output string
	for key, value := range v {
		output += fmt.Sprintf("%s: %d\n", key, value)
	}
	return output
}
<commit_msg>version.Equal implemented<commit_after>package shared

import (
	"fmt"
	"log"
)

/*
Version implements a vector clock.
*/
type Version map[string]int

/*
Increase the version for the given peer based on the already existing versions.
*/
func (v Version) Increase(selfid string) {
	/*TODO catch overflow on version increase!*/
	v[selfid] = v.Max() + 1
}

/*
Max version number from all listed peers.
*/
func (v Version) Max() int {
	var max int
	for _, value := range v {
		if value >= max {
			max = value
		}
	}
	return max
}

/*
Valid checks whether the version can be automerged or whether manual resolution
is required.
*/
func (v Version) Valid(that Version, selfid string) (Version, bool) {
	if v.Max() > that.Max() {
		// local version is ahead
		log.Println("Local version is ahead of remote version!")
		return v, false
	}
	// if local changes don't even exist no need to check the following
	_, ok := v[selfid]
	if ok && v[selfid] != that[selfid] {
		// this means local version was changed without the other peer realizing
		log.Println("Merge conflict! Local file has since changed.")
		return v, false
	}
	// otherwise we can update
	return that, true
}

/*
Equal checks whether the version per id match perfectly between the two.
*/
func (v Version) Equal(that Version) bool {
	// nil check
	if that == nil {
		return false
	}
	// length must be same
	if len(v) != len(that) {
		return false
	}
	// all entries must match
	for id, value := range v {
		thatValue, exists := that[id]
		if !exists || thatValue != value {
			return false
		}
	}
	// if everything runs through successfully, true
	return true
}

/*
String representation of version.
*/
func (v Version) String() string {
	var output string
	for key, value := range v {
		output += fmt.Sprintf("%s: %d\n", key, value)
	}
	return output
}
<|endoftext|>


<commit_before>package main

const Version string = "0.1.0"
<commit_msg>bump version to 0.1.1.<commit_after>package main

const Version string = "0.1.1"
<|endoftext|>


<commit_before>package cloudstack

const Version string = "v0.9.2"
<commit_msg>bump to 0.9.3<commit_after>package cloudstack

const Version string = "v0.9.3"
<|endoftext|>


<commit_before>package mtree

import "fmt"

const (
	// AppName is the name ... of this library/application
	AppName = "gomtree"
)

const (
	// VersionMajor is for an API incompatible changes
	VersionMajor = 0
	// VersionMinor is for functionality in a backwards-compatible manner
	VersionMinor = 4
	// VersionPatch is for backwards-compatible bug fixes
	VersionPatch = 0

	// VersionDev indicates development branch. Releases will be empty string.
	VersionDev = ""
)

// Version is the specification version that the package types support.
var Version = fmt.Sprintf("%d.%d.%d%s", VersionMajor, VersionMinor, VersionPatch, VersionDev)
<commit_msg>version: master back to -dev<commit_after>package mtree

import "fmt"

const (
	// AppName is the name ... of this library/application
	AppName = "gomtree"
)

const (
	// VersionMajor is for an API incompatible changes
	VersionMajor = 0
	// VersionMinor is for functionality in a backwards-compatible manner
	VersionMinor = 5
	// VersionPatch is for backwards-compatible bug fixes
	VersionPatch = 0

	// VersionDev indicates development branch. Releases will be empty string.
	VersionDev = "-dev"
)

// Version is the specification version that the package types support.
var Version = fmt.Sprintf("%d.%d.%d%s", VersionMajor, VersionMinor, VersionPatch, VersionDev)
<|endoftext|>


<commit_before>//
//  Important -- when you're creating a new cb-cli version for github,
//  set the cbCliVersion string var below before pushing to github.
//  -swm
//
package main

var cbCliVersion = "3.0"
<commit_msg>bump version to v4.0<commit_after>//
//  Important -- when you're creating a new cb-cli version for github,
//  set the cbCliVersion string var below before pushing to github.
//  -swm
//
package main

var cbCliVersion = "4.0"
<|endoftext|>


<commit_before>package main

import "gopkg.in/h2non/bimg.v1"

// Version stores the current package semantic version
const Version = "1.0.15"

// Version represents the supported version
type Versions struct {
	ImaginaryVersion string `json:"imaginary"`
	BimgVersion      string `json:"bimg"`
	VipsVersion      string `json:"libvips"`
}

// CurrentVersions stores the current runtime system version metadata
var CurrentVersions = Versions{Version, bimg.Version, bimg.VipsVersion}
<commit_msg>Comment fix<commit_after>package main

import "gopkg.in/h2non/bimg.v1"

// Version stores the current package semantic version
const Version = "1.0.15"

// Versions represents the used versions for several significant dependencies
type Versions struct {
	ImaginaryVersion string `json:"imaginary"`
	BimgVersion      string `json:"bimg"`
	VipsVersion      string `json:"libvips"`
}

// CurrentVersions stores the current runtime system version metadata
var CurrentVersions = Versions{Version, bimg.Version, bimg.VipsVersion}
<|endoftext|>


<commit_before>package flect

//Version holds Flect version number
const Version = "v0.1.1"
<commit_msg>version bump: v0.1.2<commit_after>package flect

//Version holds Flect version number
const Version = "v0.1.2"
<|endoftext|>


<commit_before>// Note to self : never try to code while looking after your kids
// The result might look like this : https://pbs.twimg.com/media/BXqSuYXIEAAscVA.png

package syslogparser

import (
	"fmt"
	"math"
	"strconv"
	"time"
)

func newRfc5424Parser(buff []byte, cursor int, l int) *rfc5424Parser {
	return &rfc5424Parser{
		buff:   buff,
		cursor: cursor,
		l:      l,
	}
}

// https://tools.ietf.org/html/rfc5424#section-6.2.3
func (p *rfc5424Parser) parseTimestamp() (time.Time, error) {
	var ts time.Time

	fd, err := parseFullDate(p.buff, &p.cursor, p.l)
	if err != nil {
		return ts, err
	}

	if p.buff[p.cursor] != 'T' {
		return ts, ErrInvalidTimeFormat
	}
	p.cursor++

	ft, err := parseFullTime(p.buff, &p.cursor, p.l)
	if err != nil {
		return ts, ErrTimestampUnknownFormat
	}

	nSec, err := toNSec(ft.pt.secFrac)
	if err != nil {
		return ts, err
	}

	ts = time.Date(
		fd.year,
		time.Month(fd.month),
		fd.day,
		ft.pt.hour,
		ft.pt.minute,
		ft.pt.seconds,
		nSec,
		ft.loc,
	)

	return ts, nil
}

func (p *rfc5424Parser) parseHostname() (string, error) {
	return parseHostname(p.buff, &p.cursor, p.l)
}

// APP-NAME = NILVALUE / 1*48PRINTUSASCII
func (p *rfc5424Parser) parseAppName() (string, error) {
	var to int
	var found bool
	var appName string

	maxAppNameLen := 48
	max := to + maxAppNameLen

	for to = p.cursor; (to < max) && (to < p.l); to++ {
		if p.buff[to] == ' ' {
			found = true
			break
		}
	}

	if found {
		appName = string(p.buff[p.cursor:to])
	}

	p.cursor = to

	if found {
		return appName, nil
	}

	return "", ErrInvalidAppName
}

// ----------------------------------------------
// https://tools.ietf.org/html/rfc5424#section-6
// ----------------------------------------------

// XXX : bind them to rfc5424Parser ?

// FULL-DATE : DATE-FULLYEAR "-" DATE-MONTH "-" DATE-MDAY
func parseFullDate(buff []byte, cursor *int, l int) (rfc5424FullDate, error) {
	var fd rfc5424FullDate

	year, err := parseYear(buff, cursor, l)
	if err != nil {
		return fd, err
	}

	if buff[*cursor] != '-' {
		return fd, ErrTimestampUnknownFormat
	}

	*cursor++

	month, err := parseMonth(buff, cursor, l)
	if err != nil {
		return fd, err
	}

	if buff[*cursor] != '-' {
		return fd, ErrTimestampUnknownFormat
	}

	*cursor++

	day, err := parseDay(buff, cursor, l)
	if err != nil {
		return fd, err
	}

	fd = rfc5424FullDate{
		year:  year,
		month: month,
		day:   day,
	}

	return fd, nil
}

// DATE-FULLYEAR   = 4DIGIT
func parseYear(buff []byte, cursor *int, l int) (int, error) {
	yearLen := 4

	if *cursor+yearLen > l {
		return 0, ErrEOL
	}

	// XXX : we do not check for a valid year (ie. 1999, 2013 etc)
	// XXX : we only checks the format is correct
	sub := string(buff[*cursor : *cursor+yearLen])

	*cursor += yearLen

	year, err := strconv.Atoi(sub)
	if err != nil {
		return 0, ErrYearInvalid
	}

	return year, nil
}

// DATE-MONTH = 2DIGIT  ; 01-12
func parseMonth(buff []byte, cursor *int, l int) (int, error) {
	return parse2Digits(buff, cursor, l, 1, 12, ErrMonthInvalid)
}

// DATE-MDAY = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on month/year
func parseDay(buff []byte, cursor *int, l int) (int, error) {
	// XXX : this is a relaxed constraint
	// XXX : we do not check if valid regarding February or leap years
	// XXX : we only checks that day is in range [01 -> 31]
	// XXX : in other words this function will not rant if you provide Feb 31th
	return parse2Digits(buff, cursor, l, 1, 31, ErrDayInvalid)
}

// FULL-TIME = PARTIAL-TIME TIME-OFFSET
func parseFullTime(buff []byte, cursor *int, l int) (rfc5424FullTime, error) {
	var loc = new(time.Location)
	var ft rfc5424FullTime

	pt, err := parsePartialTime(buff, cursor, l)
	if err != nil {
		return ft, err
	}

	loc, err = parseTimeOffset(buff, cursor, l)
	if err != nil {
		return ft, err
	}

	ft = rfc5424FullTime{
		pt:  pt,
		loc: loc,
	}

	return ft, nil
}

// PARTIAL-TIME = TIME-HOUR ":" TIME-MINUTE ":" TIME-SECOND[TIME-SECFRAC]
func parsePartialTime(buff []byte, cursor *int, l int) (rfc5424PartialTime, error) {
	var pt rfc5424PartialTime

	hour, minute, err := getHourMinute(buff, cursor, l)
	if err != nil {
		return pt, err
	}

	if buff[*cursor] != ':' {
		return pt, ErrInvalidTimeFormat
	}

	*cursor++

	// ----

	seconds, err := parseSecond(buff, cursor, l)
	if err != nil {
		return pt, err
	}

	pt = rfc5424PartialTime{
		hour:    hour,
		minute:  minute,
		seconds: seconds,
	}

	// ----

	if buff[*cursor] != '.' {
		return pt, nil
	}

	*cursor++

	secFrac, err := parseSecFrac(buff, cursor, l)
	if err != nil {
		return pt, nil
	}
	pt.secFrac = secFrac

	return pt, nil
}

// TIME-HOUR = 2DIGIT  ; 00-23
func parseHour(buff []byte, cursor *int, l int) (int, error) {
	return parse2Digits(buff, cursor, l, 0, 23, ErrHourInvalid)
}

// TIME-MINUTE = 2DIGIT  ; 00-59
func parseMinute(buff []byte, cursor *int, l int) (int, error) {
	return parse2Digits(buff, cursor, l, 0, 59, ErrMinuteInvalid)
}

// TIME-SECOND = 2DIGIT  ; 00-59
func parseSecond(buff []byte, cursor *int, l int) (int, error) {
	return parse2Digits(buff, cursor, l, 0, 59, ErrSecondInvalid)
}

// TIME-SECFRAC = "." 1*6DIGIT
func parseSecFrac(buff []byte, cursor *int, l int) (float64, error) {
	maxDigitLen := 6

	max := *cursor + maxDigitLen
	from := *cursor
	to := from

	for to = from; to < max; to++ {
		if to >= l {
			break
		}

		c := buff[to]
		if !isDigit(c) {
			break
		}
	}

	sub := string(buff[from:to])
	if len(sub) == 0 {
		return 0, ErrSecFracInvalid
	}

	secFrac, err := strconv.ParseFloat("0."+sub, 64)
	*cursor = to
	if err != nil {
		return 0, ErrSecFracInvalid
	}

	return secFrac, nil
}

// TIME-OFFSET = "Z" / TIME-NUMOFFSET
func parseTimeOffset(buff []byte, cursor *int, l int) (*time.Location, error) {

	if buff[*cursor] == 'Z' {
		*cursor++
		return time.UTC, nil
	}

	return parseNumericalTimeOffset(buff, cursor, l)
}

// TIME-NUMOFFSET  = ("+" / "-") TIME-HOUR ":" TIME-MINUTE
func parseNumericalTimeOffset(buff []byte, cursor *int, l int) (*time.Location, error) {
	var loc = new(time.Location)

	sign := buff[*cursor]

	if (sign != '+') && (sign != '-') {
		return loc, ErrTimeZoneInvalid
	}

	*cursor++

	hour, minute, err := getHourMinute(buff, cursor, l)
	if err != nil {
		return loc, err
	}

	tzStr := fmt.Sprintf("%s%02d:%02d", string(sign), hour, minute)
	tmpTs, err := time.Parse("-07:00", tzStr)
	if err != nil {
		return loc, err
	}

	return tmpTs.Location(), nil
}

func getHourMinute(buff []byte, cursor *int, l int) (int, int, error) {
	hour, err := parseHour(buff, cursor, l)
	if err != nil {
		return 0, 0, err
	}

	if buff[*cursor] != ':' {
		return 0, 0, ErrInvalidTimeFormat
	}

	*cursor++

	minute, err := parseMinute(buff, cursor, l)
	if err != nil {
		return 0, 0, err
	}

	return hour, minute, nil
}

func toNSec(sec float64) (int, error) {
	_, frac := math.Modf(sec)
	fracStr := strconv.FormatFloat(frac, 'f', 9, 64)
	fracInt, err := strconv.Atoi(fracStr[2:])
	if err != nil {
		return 0, err
	}

	return fracInt, nil
}
<commit_msg>Added parseUpToLen<commit_after>// Note to self : never try to code while looking after your kids
// The result might look like this : https://pbs.twimg.com/media/BXqSuYXIEAAscVA.png

package syslogparser

import (
	"fmt"
	"math"
	"strconv"
	"time"
)

func newRfc5424Parser(buff []byte, cursor int, l int) *rfc5424Parser {
	return &rfc5424Parser{
		buff:   buff,
		cursor: cursor,
		l:      l,
	}
}

// https://tools.ietf.org/html/rfc5424#section-6.2.3
func (p *rfc5424Parser) parseTimestamp() (time.Time, error) {
	var ts time.Time

	fd, err := parseFullDate(p.buff, &p.cursor, p.l)
	if err != nil {
		return ts, err
	}

	if p.buff[p.cursor] != 'T' {
		return ts, ErrInvalidTimeFormat
	}
	p.cursor++

	ft, err := parseFullTime(p.buff, &p.cursor, p.l)
	if err != nil {
		return ts, ErrTimestampUnknownFormat
	}

	nSec, err := toNSec(ft.pt.secFrac)
	if err != nil {
		return ts, err
	}

	ts = time.Date(
		fd.year,
		time.Month(fd.month),
		fd.day,
		ft.pt.hour,
		ft.pt.minute,
		ft.pt.seconds,
		nSec,
		ft.loc,
	)

	return ts, nil
}

func (p *rfc5424Parser) parseHostname() (string, error) {
	return parseHostname(p.buff, &p.cursor, p.l)
}

// APP-NAME = NILVALUE / 1*48PRINTUSASCII
func (p *rfc5424Parser) parseAppName() (string, error) {
	var to int
	var found bool
	var appName string

	maxAppNameLen := 48
	max := to + maxAppNameLen

	for to = p.cursor; (to < max) && (to < p.l); to++ {
		if p.buff[to] == ' ' {
			found = true
			break
		}
	}

	if found {
		appName = string(p.buff[p.cursor:to])
	}

	p.cursor = to

	if found {
		return appName, nil
	}

	return "", ErrInvalidAppName
}

// ----------------------------------------------
// https://tools.ietf.org/html/rfc5424#section-6
// ----------------------------------------------

// XXX : bind them to rfc5424Parser ?

// FULL-DATE : DATE-FULLYEAR "-" DATE-MONTH "-" DATE-MDAY
func parseFullDate(buff []byte, cursor *int, l int) (rfc5424FullDate, error) {
	var fd rfc5424FullDate

	year, err := parseYear(buff, cursor, l)
	if err != nil {
		return fd, err
	}

	if buff[*cursor] != '-' {
		return fd, ErrTimestampUnknownFormat
	}

	*cursor++

	month, err := parseMonth(buff, cursor, l)
	if err != nil {
		return fd, err
	}

	if buff[*cursor] != '-' {
		return fd, ErrTimestampUnknownFormat
	}

	*cursor++

	day, err := parseDay(buff, cursor, l)
	if err != nil {
		return fd, err
	}

	fd = rfc5424FullDate{
		year:  year,
		month: month,
		day:   day,
	}

	return fd, nil
}

// DATE-FULLYEAR   = 4DIGIT
func parseYear(buff []byte, cursor *int, l int) (int, error) {
	yearLen := 4

	if *cursor+yearLen > l {
		return 0, ErrEOL
	}

	// XXX : we do not check for a valid year (ie. 1999, 2013 etc)
	// XXX : we only checks the format is correct
	sub := string(buff[*cursor : *cursor+yearLen])

	*cursor += yearLen

	year, err := strconv.Atoi(sub)
	if err != nil {
		return 0, ErrYearInvalid
	}

	return year, nil
}

// DATE-MONTH = 2DIGIT  ; 01-12
func parseMonth(buff []byte, cursor *int, l int) (int, error) {
	return parse2Digits(buff, cursor, l, 1, 12, ErrMonthInvalid)
}

// DATE-MDAY = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on month/year
func parseDay(buff []byte, cursor *int, l int) (int, error) {
	// XXX : this is a relaxed constraint
	// XXX : we do not check if valid regarding February or leap years
	// XXX : we only checks that day is in range [01 -> 31]
	// XXX : in other words this function will not rant if you provide Feb 31th
	return parse2Digits(buff, cursor, l, 1, 31, ErrDayInvalid)
}

// FULL-TIME = PARTIAL-TIME TIME-OFFSET
func parseFullTime(buff []byte, cursor *int, l int) (rfc5424FullTime, error) {
	var loc = new(time.Location)
	var ft rfc5424FullTime

	pt, err := parsePartialTime(buff, cursor, l)
	if err != nil {
		return ft, err
	}

	loc, err = parseTimeOffset(buff, cursor, l)
	if err != nil {
		return ft, err
	}

	ft = rfc5424FullTime{
		pt:  pt,
		loc: loc,
	}

	return ft, nil
}

// PARTIAL-TIME = TIME-HOUR ":" TIME-MINUTE ":" TIME-SECOND[TIME-SECFRAC]
func parsePartialTime(buff []byte, cursor *int, l int) (rfc5424PartialTime, error) {
	var pt rfc5424PartialTime

	hour, minute, err := getHourMinute(buff, cursor, l)
	if err != nil {
		return pt, err
	}

	if buff[*cursor] != ':' {
		return pt, ErrInvalidTimeFormat
	}

	*cursor++

	// ----

	seconds, err := parseSecond(buff, cursor, l)
	if err != nil {
		return pt, err
	}

	pt = rfc5424PartialTime{
		hour:    hour,
		minute:  minute,
		seconds: seconds,
	}

	// ----

	if buff[*cursor] != '.' {
		return pt, nil
	}

	*cursor++

	secFrac, err := parseSecFrac(buff, cursor, l)
	if err != nil {
		return pt, nil
	}
	pt.secFrac = secFrac

	return pt, nil
}

// TIME-HOUR = 2DIGIT  ; 00-23
func parseHour(buff []byte, cursor *int, l int) (int, error) {
	return parse2Digits(buff, cursor, l, 0, 23, ErrHourInvalid)
}

// TIME-MINUTE = 2DIGIT  ; 00-59
func parseMinute(buff []byte, cursor *int, l int) (int, error) {
	return parse2Digits(buff, cursor, l, 0, 59, ErrMinuteInvalid)
}

// TIME-SECOND = 2DIGIT  ; 00-59
func parseSecond(buff []byte, cursor *int, l int) (int, error) {
	return parse2Digits(buff, cursor, l, 0, 59, ErrSecondInvalid)
}

// TIME-SECFRAC = "." 1*6DIGIT
func parseSecFrac(buff []byte, cursor *int, l int) (float64, error) {
	maxDigitLen := 6

	max := *cursor + maxDigitLen
	from := *cursor
	to := from

	for to = from; to < max; to++ {
		if to >= l {
			break
		}

		c := buff[to]
		if !isDigit(c) {
			break
		}
	}

	sub := string(buff[from:to])
	if len(sub) == 0 {
		return 0, ErrSecFracInvalid
	}

	secFrac, err := strconv.ParseFloat("0."+sub, 64)
	*cursor = to
	if err != nil {
		return 0, ErrSecFracInvalid
	}

	return secFrac, nil
}

// TIME-OFFSET = "Z" / TIME-NUMOFFSET
func parseTimeOffset(buff []byte, cursor *int, l int) (*time.Location, error) {

	if buff[*cursor] == 'Z' {
		*cursor++
		return time.UTC, nil
	}

	return parseNumericalTimeOffset(buff, cursor, l)
}

// TIME-NUMOFFSET  = ("+" / "-") TIME-HOUR ":" TIME-MINUTE
func parseNumericalTimeOffset(buff []byte, cursor *int, l int) (*time.Location, error) {
	var loc = new(time.Location)

	sign := buff[*cursor]

	if (sign != '+') && (sign != '-') {
		return loc, ErrTimeZoneInvalid
	}

	*cursor++

	hour, minute, err := getHourMinute(buff, cursor, l)
	if err != nil {
		return loc, err
	}

	tzStr := fmt.Sprintf("%s%02d:%02d", string(sign), hour, minute)
	tmpTs, err := time.Parse("-07:00", tzStr)
	if err != nil {
		return loc, err
	}

	return tmpTs.Location(), nil
}

func getHourMinute(buff []byte, cursor *int, l int) (int, int, error) {
	hour, err := parseHour(buff, cursor, l)
	if err != nil {
		return 0, 0, err
	}

	if buff[*cursor] != ':' {
		return 0, 0, ErrInvalidTimeFormat
	}

	*cursor++

	minute, err := parseMinute(buff, cursor, l)
	if err != nil {
		return 0, 0, err
	}

	return hour, minute, nil
}

func toNSec(sec float64) (int, error) {
	_, frac := math.Modf(sec)
	fracStr := strconv.FormatFloat(frac, 'f', 9, 64)
	fracInt, err := strconv.Atoi(fracStr[2:])
	if err != nil {
		return 0, err
	}

	return fracInt, nil
}

func parseUpToLen(buff []byte, cursor *int, l int, maxLen int, e error) (string, error) {
	var to int
	var found bool
	var result string

	max := to + maxLen

	for to = *cursor; (to < max) && (to < l); to++ {
		if buff[to] == ' ' {
			found = true
			break
		}
	}

	if found {
		result = string(buff[*cursor:to])
	}

	*cursor = to

	if found {
		return result, nil
	}

	return "", e
}
<|endoftext|>


<commit_before>package version

import (
	"bytes"
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)

// The compiled regular expression used to test the validity of a version.
var (
	versionRegexp *regexp.Regexp
	semverRegexp  *regexp.Regexp
)

// The raw regular expression string used for testing the validity
// of a version.
const (
	VersionRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
		`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-?([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
		`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
		`?`

	// SemverRegexpRaw requires a separator between version and prerelease
	SemverRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
		`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
		`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
		`?`
)

// Version represents a single version.
type Version struct {
	metadata string
	pre      string
	segments []int64
	si       int
	original string
}

func init() {
	versionRegexp = regexp.MustCompile("^" + VersionRegexpRaw + "$")
	semverRegexp = regexp.MustCompile("^" + SemverRegexpRaw + "$")
}

// NewVersion parses the given version and returns a new
// Version.
func NewVersion(v string) (*Version, error) {
	return newVersion(v, versionRegexp)
}

// NewSemver parses the given version and returns a new
// Version that adheres strictly to SemVer specs
// https://semver.org/
func NewSemver(v string) (*Version, error) {
	return newVersion(v, semverRegexp)
}

func newVersion(v string, pattern *regexp.Regexp) (*Version, error) {
	matches := pattern.FindStringSubmatch(v)
	if matches == nil {
		return nil, fmt.Errorf("Malformed version: %s", v)
	}
	segmentsStr := strings.Split(matches[1], ".")
	segments := make([]int64, len(segmentsStr))
	si := 0
	for i, str := range segmentsStr {
		val, err := strconv.ParseInt(str, 10, 64)
		if err != nil {
			return nil, fmt.Errorf(
				"Error parsing version: %s", err)
		}

		segments[i] = int64(val)
		si++
	}

	// Even though we could support more than three segments, if we
	// got less than three, pad it with 0s. This is to cover the basic
	// default usecase of semver, which is MAJOR.MINOR.PATCH at the minimum
	for i := len(segments); i < 3; i++ {
		segments = append(segments, 0)
	}

	pre := matches[7]
	if pre == "" {
		pre = matches[4]
	}

	return &Version{
		metadata: matches[10],
		pre:      pre,
		segments: segments,
		si:       si,
		original: v,
	}, nil
}

// Must is a helper that wraps a call to a function returning (*Version, error)
// and panics if error is non-nil.
func Must(v *Version, err error) *Version {
	if err != nil {
		panic(err)
	}

	return v
}

// Compare compares this version to another version. This
// returns -1, 0, or 1 if this version is smaller, equal,
// or larger than the other version, respectively.
//
// If you want boolean results, use the LessThan, Equal,
// GreaterThan, GreaterThanOrEqual or LessThanOrEqual methods.
func (v *Version) Compare(other *Version) int {
	// A quick, efficient equality check
	if v.String() == other.String() {
		return 0
	}

	segmentsSelf := v.Segments64()
	segmentsOther := other.Segments64()

	// If the segments are the same, we must compare on prerelease info
	if reflect.DeepEqual(segmentsSelf, segmentsOther) {
		preSelf := v.Prerelease()
		preOther := other.Prerelease()
		if preSelf == "" && preOther == "" {
			return 0
		}
		if preSelf == "" {
			return 1
		}
		if preOther == "" {
			return -1
		}

		return comparePrereleases(preSelf, preOther)
	}

	// Get the highest specificity (hS), or if they're equal, just use segmentSelf length
	lenSelf := len(segmentsSelf)
	lenOther := len(segmentsOther)
	hS := lenSelf
	if lenSelf < lenOther {
		hS = lenOther
	}
	// Compare the segments
	// Because a constraint could have more/less specificity than the version it's
	// checking, we need to account for a lopsided or jagged comparison
	for i := 0; i < hS; i++ {
		if i > lenSelf-1 {
			// This means Self had the lower specificity
			// Check to see if the remaining segments in Other are all zeros
			if !allZero(segmentsOther[i:]) {
				// if not, it means that Other has to be greater than Self
				return -1
			}
			break
		} else if i > lenOther-1 {
			// this means Other had the lower specificity
			// Check to see if the remaining segments in Self are all zeros -
			if !allZero(segmentsSelf[i:]) {
				//if not, it means that Self has to be greater than Other
				return 1
			}
			break
		}
		lhs := segmentsSelf[i]
		rhs := segmentsOther[i]
		if lhs == rhs {
			continue
		} else if lhs < rhs {
			return -1
		}
		// Otherwis, rhs was > lhs, they're not equal
		return 1
	}

	// if we got this far, they're equal
	return 0
}

func allZero(segs []int64) bool {
	for _, s := range segs {
		if s != 0 {
			return false
		}
	}
	return true
}

func comparePart(preSelf string, preOther string) int {
	if preSelf == preOther {
		return 0
	}

	var selfInt int64
	selfNumeric := true
	selfInt, err := strconv.ParseInt(preSelf, 10, 64)
	if err != nil {
		selfNumeric = false
	}

	var otherInt int64
	otherNumeric := true
	otherInt, err = strconv.ParseInt(preOther, 10, 64)
	if err != nil {
		otherNumeric = false
	}

	// if a part is empty, we use the other to decide
	if preSelf == "" {
		if otherNumeric {
			return -1
		}
		return 1
	}

	if preOther == "" {
		if selfNumeric {
			return 1
		}
		return -1
	}

	if selfNumeric && !otherNumeric {
		return -1
	} else if !selfNumeric && otherNumeric {
		return 1
	} else if !selfNumeric && !otherNumeric && preSelf > preOther {
		return 1
	} else if selfInt > otherInt {
		return 1
	}

	return -1
}

func comparePrereleases(v string, other string) int {
	// the same pre release!
	if v == other {
		return 0
	}

	// split both pre releases for analyse their parts
	selfPreReleaseMeta := strings.Split(v, ".")
	otherPreReleaseMeta := strings.Split(other, ".")

	selfPreReleaseLen := len(selfPreReleaseMeta)
	otherPreReleaseLen := len(otherPreReleaseMeta)

	biggestLen := otherPreReleaseLen
	if selfPreReleaseLen > otherPreReleaseLen {
		biggestLen = selfPreReleaseLen
	}

	// loop for parts to find the first difference
	for i := 0; i < biggestLen; i = i + 1 {
		partSelfPre := ""
		if i < selfPreReleaseLen {
			partSelfPre = selfPreReleaseMeta[i]
		}

		partOtherPre := ""
		if i < otherPreReleaseLen {
			partOtherPre = otherPreReleaseMeta[i]
		}

		compare := comparePart(partSelfPre, partOtherPre)
		// if parts are equals, continue the loop
		if compare != 0 {
			return compare
		}
	}

	return 0
}

// Equal tests if two versions are equal.
func (v *Version) Equal(o *Version) bool {
	return v.Compare(o) == 0
}

// GreaterThan tests if this version is greater than another version.
func (v *Version) GreaterThan(o *Version) bool {
	return v.Compare(o) > 0
}

// GreaterThanOrEqualTo tests if this version is greater than or equal to another version.
func (v *Version) GreaterThanOrEqual(o *Version) bool {
	return v.Compare(o) >= 0
}

// LessThan tests if this version is less than another version.
func (v *Version) LessThan(o *Version) bool {
	return v.Compare(o) < 0
}

// LessThanOrEqualTo tests if this version is less than or equal to another version.
func (v *Version) LessThanOrEqual(o *Version) bool {
	return v.Compare(o) <= 0
}

// Metadata returns any metadata that was part of the version
// string.
//
// Metadata is anything that comes after the "+" in the version.
// For example, with "1.2.3+beta", the metadata is "beta".
func (v *Version) Metadata() string {
	return v.metadata
}

// Prerelease returns any prerelease data that is part of the version,
// or blank if there is no prerelease data.
//
// Prerelease information is anything that comes after the "-" in the
// version (but before any metadata). For example, with "1.2.3-beta",
// the prerelease information is "beta".
func (v *Version) Prerelease() string {
	return v.pre
}

// Segments returns the numeric segments of the version as a slice of ints.
//
// This excludes any metadata or pre-release information. For example,
// for a version "1.2.3-beta", segments will return a slice of
// 1, 2, 3.
func (v *Version) Segments() []int {
	segmentSlice := make([]int, len(v.segments))
	for i, v := range v.segments {
		segmentSlice[i] = int(v)
	}
	return segmentSlice
}

// Segments64 returns the numeric segments of the version as a slice of int64s.
//
// This excludes any metadata or pre-release information. For example,
// for a version "1.2.3-beta", segments will return a slice of
// 1, 2, 3.
func (v *Version) Segments64() []int64 {
	result := make([]int64, len(v.segments))
	copy(result, v.segments)
	return result
}

// String returns the full version string included pre-release
// and metadata information.
//
// This value is rebuilt according to the parsed segments and other
// information. Therefore, ambiguities in the version string such as
// prefixed zeroes (1.04.0 => 1.4.0), `v` prefix (v1.0.0 => 1.0.0), and
// missing parts (1.0 => 1.0.0) will be made into a canonicalized form
// as shown in the parenthesized examples.
func (v *Version) String() string {
	var buf bytes.Buffer
	fmtParts := make([]string, len(v.segments))
	for i, s := range v.segments {
		// We can ignore err here since we've pre-parsed the values in segments
		str := strconv.FormatInt(s, 10)
		fmtParts[i] = str
	}
	fmt.Fprintf(&buf, strings.Join(fmtParts, "."))
	if v.pre != "" {
		fmt.Fprintf(&buf, "-%s", v.pre)
	}
	if v.metadata != "" {
		fmt.Fprintf(&buf, "+%s", v.metadata)
	}

	return buf.String()
}

// Original returns the original parsed version as-is, including any
// potential whitespace, `v` prefix, etc.
func (v *Version) Original() string {
	return v.original
}
<commit_msg>fix godoc comments<commit_after>package version

import (
	"bytes"
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)

// The compiled regular expression used to test the validity of a version.
var (
	versionRegexp *regexp.Regexp
	semverRegexp  *regexp.Regexp
)

// The raw regular expression string used for testing the validity
// of a version.
const (
	VersionRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
		`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-?([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
		`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
		`?`

	// SemverRegexpRaw requires a separator between version and prerelease
	SemverRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
		`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
		`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
		`?`
)

// Version represents a single version.
type Version struct {
	metadata string
	pre      string
	segments []int64
	si       int
	original string
}

func init() {
	versionRegexp = regexp.MustCompile("^" + VersionRegexpRaw + "$")
	semverRegexp = regexp.MustCompile("^" + SemverRegexpRaw + "$")
}

// NewVersion parses the given version and returns a new
// Version.
func NewVersion(v string) (*Version, error) {
	return newVersion(v, versionRegexp)
}

// NewSemver parses the given version and returns a new
// Version that adheres strictly to SemVer specs
// https://semver.org/
func NewSemver(v string) (*Version, error) {
	return newVersion(v, semverRegexp)
}

func newVersion(v string, pattern *regexp.Regexp) (*Version, error) {
	matches := pattern.FindStringSubmatch(v)
	if matches == nil {
		return nil, fmt.Errorf("Malformed version: %s", v)
	}
	segmentsStr := strings.Split(matches[1], ".")
	segments := make([]int64, len(segmentsStr))
	si := 0
	for i, str := range segmentsStr {
		val, err := strconv.ParseInt(str, 10, 64)
		if err != nil {
			return nil, fmt.Errorf(
				"Error parsing version: %s", err)
		}

		segments[i] = int64(val)
		si++
	}

	// Even though we could support more than three segments, if we
	// got less than three, pad it with 0s. This is to cover the basic
	// default usecase of semver, which is MAJOR.MINOR.PATCH at the minimum
	for i := len(segments); i < 3; i++ {
		segments = append(segments, 0)
	}

	pre := matches[7]
	if pre == "" {
		pre = matches[4]
	}

	return &Version{
		metadata: matches[10],
		pre:      pre,
		segments: segments,
		si:       si,
		original: v,
	}, nil
}

// Must is a helper that wraps a call to a function returning (*Version, error)
// and panics if error is non-nil.
func Must(v *Version, err error) *Version {
	if err != nil {
		panic(err)
	}

	return v
}

// Compare compares this version to another version. This
// returns -1, 0, or 1 if this version is smaller, equal,
// or larger than the other version, respectively.
//
// If you want boolean results, use the LessThan, Equal,
// GreaterThan, GreaterThanOrEqual or LessThanOrEqual methods.
func (v *Version) Compare(other *Version) int {
	// A quick, efficient equality check
	if v.String() == other.String() {
		return 0
	}

	segmentsSelf := v.Segments64()
	segmentsOther := other.Segments64()

	// If the segments are the same, we must compare on prerelease info
	if reflect.DeepEqual(segmentsSelf, segmentsOther) {
		preSelf := v.Prerelease()
		preOther := other.Prerelease()
		if preSelf == "" && preOther == "" {
			return 0
		}
		if preSelf == "" {
			return 1
		}
		if preOther == "" {
			return -1
		}

		return comparePrereleases(preSelf, preOther)
	}

	// Get the highest specificity (hS), or if they're equal, just use segmentSelf length
	lenSelf := len(segmentsSelf)
	lenOther := len(segmentsOther)
	hS := lenSelf
	if lenSelf < lenOther {
		hS = lenOther
	}
	// Compare the segments
	// Because a constraint could have more/less specificity than the version it's
	// checking, we need to account for a lopsided or jagged comparison
	for i := 0; i < hS; i++ {
		if i > lenSelf-1 {
			// This means Self had the lower specificity
			// Check to see if the remaining segments in Other are all zeros
			if !allZero(segmentsOther[i:]) {
				// if not, it means that Other has to be greater than Self
				return -1
			}
			break
		} else if i > lenOther-1 {
			// this means Other had the lower specificity
			// Check to see if the remaining segments in Self are all zeros -
			if !allZero(segmentsSelf[i:]) {
				//if not, it means that Self has to be greater than Other
				return 1
			}
			break
		}
		lhs := segmentsSelf[i]
		rhs := segmentsOther[i]
		if lhs == rhs {
			continue
		} else if lhs < rhs {
			return -1
		}
		// Otherwis, rhs was > lhs, they're not equal
		return 1
	}

	// if we got this far, they're equal
	return 0
}

func allZero(segs []int64) bool {
	for _, s := range segs {
		if s != 0 {
			return false
		}
	}
	return true
}

func comparePart(preSelf string, preOther string) int {
	if preSelf == preOther {
		return 0
	}

	var selfInt int64
	selfNumeric := true
	selfInt, err := strconv.ParseInt(preSelf, 10, 64)
	if err != nil {
		selfNumeric = false
	}

	var otherInt int64
	otherNumeric := true
	otherInt, err = strconv.ParseInt(preOther, 10, 64)
	if err != nil {
		otherNumeric = false
	}

	// if a part is empty, we use the other to decide
	if preSelf == "" {
		if otherNumeric {
			return -1
		}
		return 1
	}

	if preOther == "" {
		if selfNumeric {
			return 1
		}
		return -1
	}

	if selfNumeric && !otherNumeric {
		return -1
	} else if !selfNumeric && otherNumeric {
		return 1
	} else if !selfNumeric && !otherNumeric && preSelf > preOther {
		return 1
	} else if selfInt > otherInt {
		return 1
	}

	return -1
}

func comparePrereleases(v string, other string) int {
	// the same pre release!
	if v == other {
		return 0
	}

	// split both pre releases for analyse their parts
	selfPreReleaseMeta := strings.Split(v, ".")
	otherPreReleaseMeta := strings.Split(other, ".")

	selfPreReleaseLen := len(selfPreReleaseMeta)
	otherPreReleaseLen := len(otherPreReleaseMeta)

	biggestLen := otherPreReleaseLen
	if selfPreReleaseLen > otherPreReleaseLen {
		biggestLen = selfPreReleaseLen
	}

	// loop for parts to find the first difference
	for i := 0; i < biggestLen; i = i + 1 {
		partSelfPre := ""
		if i < selfPreReleaseLen {
			partSelfPre = selfPreReleaseMeta[i]
		}

		partOtherPre := ""
		if i < otherPreReleaseLen {
			partOtherPre = otherPreReleaseMeta[i]
		}

		compare := comparePart(partSelfPre, partOtherPre)
		// if parts are equals, continue the loop
		if compare != 0 {
			return compare
		}
	}

	return 0
}

// Equal tests if two versions are equal.
func (v *Version) Equal(o *Version) bool {
	return v.Compare(o) == 0
}

// GreaterThan tests if this version is greater than another version.
func (v *Version) GreaterThan(o *Version) bool {
	return v.Compare(o) > 0
}

// GreaterThanOrEqual tests if this version is greater than or equal to another version.
func (v *Version) GreaterThanOrEqual(o *Version) bool {
	return v.Compare(o) >= 0
}

// LessThan tests if this version is less than another version.
func (v *Version) LessThan(o *Version) bool {
	return v.Compare(o) < 0
}

// LessThanOrEqual tests if this version is less than or equal to another version.
func (v *Version) LessThanOrEqual(o *Version) bool {
	return v.Compare(o) <= 0
}

// Metadata returns any metadata that was part of the version
// string.
//
// Metadata is anything that comes after the "+" in the version.
// For example, with "1.2.3+beta", the metadata is "beta".
func (v *Version) Metadata() string {
	return v.metadata
}

// Prerelease returns any prerelease data that is part of the version,
// or blank if there is no prerelease data.
//
// Prerelease information is anything that comes after the "-" in the
// version (but before any metadata). For example, with "1.2.3-beta",
// the prerelease information is "beta".
func (v *Version) Prerelease() string {
	return v.pre
}

// Segments returns the numeric segments of the version as a slice of ints.
//
// This excludes any metadata or pre-release information. For example,
// for a version "1.2.3-beta", segments will return a slice of
// 1, 2, 3.
func (v *Version) Segments() []int {
	segmentSlice := make([]int, len(v.segments))
	for i, v := range v.segments {
		segmentSlice[i] = int(v)
	}
	return segmentSlice
}

// Segments64 returns the numeric segments of the version as a slice of int64s.
//
// This excludes any metadata or pre-release information. For example,
// for a version "1.2.3-beta", segments will return a slice of
// 1, 2, 3.
func (v *Version) Segments64() []int64 {
	result := make([]int64, len(v.segments))
	copy(result, v.segments)
	return result
}

// String returns the full version string included pre-release
// and metadata information.
//
// This value is rebuilt according to the parsed segments and other
// information. Therefore, ambiguities in the version string such as
// prefixed zeroes (1.04.0 => 1.4.0), `v` prefix (v1.0.0 => 1.0.0), and
// missing parts (1.0 => 1.0.0) will be made into a canonicalized form
// as shown in the parenthesized examples.
func (v *Version) String() string {
	var buf bytes.Buffer
	fmtParts := make([]string, len(v.segments))
	for i, s := range v.segments {
		// We can ignore err here since we've pre-parsed the values in segments
		str := strconv.FormatInt(s, 10)
		fmtParts[i] = str
	}
	fmt.Fprintf(&buf, strings.Join(fmtParts, "."))
	if v.pre != "" {
		fmt.Fprintf(&buf, "-%s", v.pre)
	}
	if v.metadata != "" {
		fmt.Fprintf(&buf, "+%s", v.metadata)
	}

	return buf.String()
}

// Original returns the original parsed version as-is, including any
// potential whitespace, `v` prefix, etc.
func (v *Version) Original() string {
	return v.original
}
<|endoftext|>


<commit_before>package main

const VERSION = "0.1.0.rc1"
<commit_msg>Bump version<commit_after>package main

const VERSION = "0.1.0.rc2"
<|endoftext|>


<commit_before>// Copyright 2021 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 ebiten

import (
	"time"
)

// VibrateOptions represents the options for device vibration.
type VibrateOptions struct {
	// Duration is the time duration of the effect.
	Duration time.Duration

	// Intensity is the strength of the device vibration.
	// The value is in between 0 and 1.
	Intensity float64
}

// Vibrate vibrates the device with the specified options.
//
// Vibrate works on mobiles and browsers.
//
// On browsers, Intensity in the options is ignored.
//
// On Android, this line is required in the manifest setting to use the vibration:
//
//     <uses-permission android:name="android.permission.VIBRATE"/>
//
// On Android, Intensity in the options is recognized only when the API Level is 26 or newer.
// Otherwise, Intensity is ignored.
//
// On iOS, Vibrate works only when iOS version is 13.0 or newer.
// Otherwise, Vibrate does nothing.
//
// Vibrate is concurrent-safe.
func Vibrate(options *VibrateOptions) {
	uiDriver().Vibrate(options.Duration, options.Intensity)
}

// VibrateGamepadOptions represents the options for gamepad vibration.
type VibrateGamepadOptions struct {
	// Duration is the time duration of the effect.
	Duration time.Duration

	// StrongMagnitude is the rumble intensity of a low-frequency rumble motor.
	// The value is in between 0 and 1.
	StrongMagnitude float64

	// StrongMagnitude is the rumble intensity of a high-frequency rumble motor.
	// The value is in between 0 and 1.
	WeakMagnitude float64
}

// VibrateGamepad vibrates the specified gamepad with the specified options.
//
// VibrateGamepad is concurrent-safe.
func VibrateGamepad(gamepadID GamepadID, options *VibrateGamepadOptions) {
	uiDriver().Input().VibrateGamepad(gamepadID, options.Duration, options.StrongMagnitude, options.WeakMagnitude)
}
<commit_msg>ebiten: Add comments about Vibrate<commit_after>// Copyright 2021 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 ebiten

import (
	"time"
)

// VibrateOptions represents the options for device vibration.
type VibrateOptions struct {
	// Duration is the time duration of the effect.
	Duration time.Duration

	// Intensity is the strength of the device vibration.
	// The value is in between 0 and 1.
	Intensity float64
}

// Vibrate vibrates the device with the specified options.
//
// Vibrate works on mobiles and browsers.
//
// On browsers, Intensity in the options is ignored.
//
// On Android, this line is required in the manifest setting to use Vibrate:
//
//     <uses-permission android:name="android.permission.VIBRATE"/>
//
// On Android, Intensity in the options is recognized only when the API Level is 26 or newer.
// Otherwise, Intensity is ignored.
//
// On iOS, CoreHaptics.framework is required to use Vibrate.
//
// On iOS, Vibrate works only when iOS version is 13.0 or newer.
// Otherwise, Vibrate does nothing.
//
// Vibrate is concurrent-safe.
func Vibrate(options *VibrateOptions) {
	uiDriver().Vibrate(options.Duration, options.Intensity)
}

// VibrateGamepadOptions represents the options for gamepad vibration.
type VibrateGamepadOptions struct {
	// Duration is the time duration of the effect.
	Duration time.Duration

	// StrongMagnitude is the rumble intensity of a low-frequency rumble motor.
	// The value is in between 0 and 1.
	StrongMagnitude float64

	// StrongMagnitude is the rumble intensity of a high-frequency rumble motor.
	// The value is in between 0 and 1.
	WeakMagnitude float64
}

// VibrateGamepad vibrates the specified gamepad with the specified options.
//
// VibrateGamepad is concurrent-safe.
func VibrateGamepad(gamepadID GamepadID, options *VibrateGamepadOptions) {
	uiDriver().Input().VibrateGamepad(gamepadID, options.Duration, options.StrongMagnitude, options.WeakMagnitude)
}
<|endoftext|>


<commit_before>package main

import (
	_ "github.com/sheenobu/quicklog/filters/uuid"
	"github.com/sheenobu/quicklog/inputs/stdin"
	_ "github.com/sheenobu/quicklog/outputs/stdout"
	_ "github.com/sheenobu/quicklog/parsers/plain"

	"golang.org/x/net/context"

	"github.com/sheenobu/quicklog/ql"
)

func main() {

	chain := ql.Chain{
		Input:  &stdin.Process{},
		Output: ql.GetOutput("stdout"),
		Filter: ql.GetFilter("uuid"),
		Parser: ql.GetParser("plain"),
	}

	ctx := context.Background()
	chain.Execute(ctx)

}
<commit_msg>Convert embedded example to use objects directly<commit_after>package main

import (
	"github.com/sheenobu/quicklog/filters/uuid"
	"github.com/sheenobu/quicklog/inputs/stdin"
	"github.com/sheenobu/quicklog/outputs/debug"
	"github.com/sheenobu/quicklog/parsers/plain"

	"golang.org/x/net/context"

	"github.com/sheenobu/quicklog/ql"
)

func main() {

	chain := ql.Chain{
		Input: &stdin.Process{},
		//Output: &stdout.Process{},
		Output: &debug.Handler{PrintFields: debug.NullableBool{NotNull: false, Value: true}},
		Filter: &uuid.Handler{FieldName: "uuid"},
		Parser: &plain.Parser{},
	}

	ctx := context.Background()
	chain.Execute(ctx)

}
<|endoftext|>


<commit_before>package vtclean

import (
	"regexp"
	"strconv"
)

// see regex.txt for a slightly separated version of this regex
var vt100re = regexp.MustCompile(`^\033(([A-KZ=>12<]|Y\d{2})|\[\d+[A-D]|\[\d+;\d+[Hf]|#[1-68]|\[(\d+|;)*[qm]|\[[KJg]|\[[0-2]K|\[[02]J|\([ABCEHKQRYZ0-7=]|[\[K]\d+;\d+r|\[[03]g|\[\?[1-9][lh]|\[20[lh]|\[[56]n|\[0?c|\[2;[1248]y|\[!p|\[([01457]|254)}|\[\?(12;)?(25|50)[lh]|[78DEHM]|\[[ABCDHJKLMP]|\[4[hl]|\[\?1[46][hl]|\[\*[LMP]|\[[12][JK]|\]\d*;\d*[^\x07]+\x07|\[\d*[@ABCDEFGIJKLMPSTXZ1abcdeghilmnp])`)
var vt100color = regexp.MustCompile(`^\033\[(\d+|;)*[m]`)
var lineEdit = regexp.MustCompile(`^\033\[(\d*)([CDPK])`)

func vt100scan(line string) int {
	return len(vt100re.FindString(line))
}

func isColor(line string) bool {
	return len(vt100color.FindString(line)) > 0
}

func Clean(line string, color bool) string {
	out := make([]rune, len(line))
	liner := []rune(line)
	hadColor := false
	pos, max := 0, 0
	for i := 0; i < len(liner); {
		c := liner[i]
		str := string(liner[i:])
		switch c {
		case '\b':
			pos -= 1
		case '\x7f':
			copy(out[pos:max], out[pos+1:max])
			max -= 1
		case '\033':
			if m := lineEdit.FindStringSubmatch(str); m != nil {
				i += len(lineEdit.FindString(str))
				n, err := strconv.Atoi(m[1])
				if err != nil || n > 10000 {
					n = 1
				}
				switch m[2] {
				case "C":
					pos += n
				case "D":
					pos -= n
				case "P":
					most := max - pos
					if n > most {
						n = most
					}
					copy(out[pos:], out[pos+n:])
					max -= n
				case "K":
					switch m[1] {
					case "", "0":
						max = pos
					case "1":
						copy(out, out[pos:])
						max = pos
					case "2":
						pos, max = 0, 0
					}
				}
				if pos < 0 {
					pos = 0
				}
				if pos > max {
					pos = max
				}
				continue
			}
			if !(color && isColor(str)) {
				skip := vt100scan(str)
				if skip > 0 {
					i += skip
					continue
				}
			} else {
				hadColor = true
				out[pos] = c
				pos++
			}
		default:
			if c == '\n' || c >= ' ' {
				out[pos] = c
				pos++
			}
		}
		if pos > max {
			max = pos
		}
		i += 1
	}
	out = out[:max]
	if hadColor {
		out = append(out, []rune("\033[0m")...)
	}
	return string(out)
}
<commit_msg>add line editing '@'<commit_after>package vtclean

import (
	"regexp"
	"strconv"
)

// see regex.txt for a slightly separated version of this regex
var vt100re = regexp.MustCompile(`^\033(([A-KZ=>12<]|Y\d{2})|\[\d+[A-D]|\[\d+;\d+[Hf]|#[1-68]|\[(\d+|;)*[qm]|\[[KJg]|\[[0-2]K|\[[02]J|\([ABCEHKQRYZ0-7=]|[\[K]\d+;\d+r|\[[03]g|\[\?[1-9][lh]|\[20[lh]|\[[56]n|\[0?c|\[2;[1248]y|\[!p|\[([01457]|254)}|\[\?(12;)?(25|50)[lh]|[78DEHM]|\[[ABCDHJKLMP]|\[4[hl]|\[\?1[46][hl]|\[\*[LMP]|\[[12][JK]|\]\d*;\d*[^\x07]+\x07|\[\d*[@ABCDEFGIJKLMPSTXZ1abcdeghilmnp])`)
var vt100color = regexp.MustCompile(`^\033\[(\d+|;)*[m]`)
var lineEdit = regexp.MustCompile(`^\033\[(\d*)([@CDPK])`)

func vt100scan(line string) int {
	return len(vt100re.FindString(line))
}

func isColor(line string) bool {
	return len(vt100color.FindString(line)) > 0
}

func Clean(line string, color bool) string {
	out := make([]rune, len(line))
	liner := []rune(line)
	hadColor := false
	pos, max := 0, 0
	for i := 0; i < len(liner); {
		c := liner[i]
		str := string(liner[i:])
		switch c {
		case '\b':
			pos -= 1
		case '\x7f':
			copy(out[pos:max], out[pos+1:max])
			max -= 1
		case '\033':
			if m := lineEdit.FindStringSubmatch(str); m != nil {
				i += len(lineEdit.FindString(str))
				n, err := strconv.Atoi(m[1])
				if err != nil || n > 10000 {
					n = 1
				}
				switch m[2] {
				case "@":
					for j := 0; j < n; j++ {
						out[pos+j] = ' '
					}
					pos += n
				case "C":
					pos += n
				case "D":
					pos -= n
				case "P":
					most := max - pos
					if n > most {
						n = most
					}
					copy(out[pos:], out[pos+n:])
					max -= n
				case "K":
					switch m[1] {
					case "", "0":
						max = pos
					case "1":
						copy(out, out[pos:])
						max = pos
					case "2":
						pos, max = 0, 0
					}
				}
				if pos < 0 {
					pos = 0
				}
				if pos > max {
					pos = max
				}
				continue
			}
			if !(color && isColor(str)) {
				skip := vt100scan(str)
				if skip > 0 {
					i += skip
					continue
				}
			} else {
				hadColor = true
				out[pos] = c
				pos++
			}
		default:
			if c == '\n' || c >= ' ' {
				out[pos] = c
				pos++
			}
		}
		if pos > max {
			max = pos
		}
		i += 1
	}
	out = out[:max]
	if hadColor {
		out = append(out, []rune("\033[0m")...)
	}
	return string(out)
}
<|endoftext|>