<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 configmap

import (
	"fmt"
	"path"

	"github.com/golang/glog"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/types"
	ioutil "k8s.io/kubernetes/pkg/util/io"
	"k8s.io/kubernetes/pkg/util/mount"
	"k8s.io/kubernetes/pkg/util/strings"
	"k8s.io/kubernetes/pkg/volume"
	volumeutil "k8s.io/kubernetes/pkg/volume/util"
)

// ProbeVolumePlugin is the entry point for plugin detection in a package.
func ProbeVolumePlugins() []volume.VolumePlugin {
	return []volume.VolumePlugin{&configMapPlugin{}}
}

const (
	configMapPluginName = "kubernetes.io/configmap"
)

// configMapPlugin implements the VolumePlugin interface.
type configMapPlugin struct {
	host volume.VolumeHost
}

var _ volume.VolumePlugin = &configMapPlugin{}

func (plugin *configMapPlugin) Init(host volume.VolumeHost) error {
	plugin.host = host
	return nil
}

func (plugin *configMapPlugin) Name() string {
	return configMapPluginName
}

func (plugin *configMapPlugin) CanSupport(spec *volume.Spec) bool {
	return spec.Volume != nil && spec.Volume.ConfigMap != nil
}

func (plugin *configMapPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) {
	return &configMapVolumeBuilder{
		configMapVolume: &configMapVolume{spec.Name(), pod.UID, plugin, plugin.host.GetMounter(), plugin.host.GetWriter(), volume.MetricsNil{}},
		source:          *spec.Volume.ConfigMap,
		pod:             *pod,
		opts:            &opts}, nil
}

func (plugin *configMapPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) {
	return &configMapVolumeCleaner{&configMapVolume{volName, podUID, plugin, plugin.host.GetMounter(), plugin.host.GetWriter(), volume.MetricsNil{}}}, nil
}

type configMapVolume struct {
	volName string
	podUID  types.UID
	plugin  *configMapPlugin
	mounter mount.Interface
	writer  ioutil.Writer
	volume.MetricsNil
}

var _ volume.Volume = &configMapVolume{}

func (sv *configMapVolume) GetPath() string {
	return sv.plugin.host.GetPodVolumeDir(sv.podUID, strings.EscapeQualifiedNameForDisk(configMapPluginName), sv.volName)
}

// configMapVolumeBuilder handles retrieving secrets from the API server
// and placing them into the volume on the host.
type configMapVolumeBuilder struct {
	*configMapVolume

	source api.ConfigMapVolumeSource
	pod    api.Pod
	opts   *volume.VolumeOptions
}

var _ volume.Builder = &configMapVolumeBuilder{}

func (sv *configMapVolume) GetAttributes() volume.Attributes {
	return volume.Attributes{
		ReadOnly:        true,
		Managed:         true,
		SupportsSELinux: true,
	}
}

func (b *configMapVolumeBuilder) getMetaDir() string {
	return path.Join(b.plugin.host.GetPodPluginDir(b.podUID, strings.EscapeQualifiedNameForDisk(configMapPluginName)), b.volName)
}

// This is the spec for the volume that this plugin wraps.
var wrappedVolumeSpec = volume.Spec{
	Volume: &api.Volume{VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageMediumMemory}}},
}

func (b *configMapVolumeBuilder) SetUp(fsGroup *int64) error {
	return b.SetUpAt(b.GetPath(), fsGroup)
}

func (b *configMapVolumeBuilder) SetUpAt(dir string, fsGroup *int64) error {
	glog.V(3).Infof("Setting up volume %v for pod %v at %v", b.volName, b.pod.UID, dir)

	// Wrap EmptyDir, let it do the setup.
	wrapped, err := b.plugin.host.NewWrapperBuilder(b.volName, wrappedVolumeSpec, &b.pod, *b.opts)
	if err != nil {
		return err
	}
	if err := wrapped.SetUpAt(dir, fsGroup); err != nil {
		return err
	}

	kubeClient := b.plugin.host.GetKubeClient()
	if kubeClient == nil {
		return fmt.Errorf("Cannot setup configMap volume %v because kube client is not configured", b.volName)
	}

	configMap, err := kubeClient.Core().ConfigMaps(b.pod.Namespace).Get(b.source.Name)
	if err != nil {
		glog.Errorf("Couldn't get configMap %v/%v: %v", b.pod.Namespace, b.source.Name, err)
		return err
	}

	totalBytes := totalBytes(configMap)
	glog.V(3).Infof("Received configMap %v/%v containing (%v) pieces of data, %v total bytes",
		b.pod.Namespace,
		b.source.Name,
		len(configMap.Data),
		totalBytes)

	payload, err := makePayload(b.source.Items, configMap)
	if err != nil {
		return err
	}

	writerContext := fmt.Sprintf("pod %v/%v volume %v", b.pod.Namespace, b.pod.Name, b.volName)
	writer, err := volumeutil.NewAtomicWriter(dir, writerContext)
	if err != nil {
		glog.Errorf("Error creating atomic writer: %v", err)
		return err
	}

	err = writer.Write(payload)
	if err != nil {
		glog.Errorf("Error writing payload to dir: %v", err)
		return err
	}

	err = volume.SetVolumeOwnership(b, fsGroup)
	if err != nil {
		glog.Errorf("Error applying volume ownership settings for group: %v", fsGroup)
		return err
	}

	return nil
}

func makePayload(mappings []api.KeyToPath, configMap *api.ConfigMap) (map[string][]byte, error) {
	payload := make(map[string][]byte, len(configMap.Data))

	if len(mappings) == 0 {
		for name, data := range configMap.Data {
			payload[name] = []byte(data)
		}
	} else {
		for _, ktp := range mappings {
			content, ok := configMap.Data[ktp.Key]
			if !ok {
				glog.Errorf("references non-existent config key")
				return nil, fmt.Errorf("references non-existent config key")
			}

			payload[ktp.Path] = []byte(content)
		}
	}

	return payload, nil
}

func totalBytes(configMap *api.ConfigMap) int {
	totalSize := 0
	for _, value := range configMap.Data {
		totalSize += len(value)
	}

	return totalSize
}

// configMapVolumeCleaner handles cleaning up configMap volumes.
type configMapVolumeCleaner struct {
	*configMapVolume
}

var _ volume.Cleaner = &configMapVolumeCleaner{}

func (c *configMapVolumeCleaner) TearDown() error {
	return c.TearDownAt(c.GetPath())
}

func (c *configMapVolumeCleaner) TearDownAt(dir string) error {
	glog.V(3).Infof("Tearing down volume %v for pod %v at %v", c.volName, c.podUID, dir)

	// Wrap EmptyDir, let it do the teardown.
	wrapped, err := c.plugin.host.NewWrapperCleaner(c.volName, wrappedVolumeSpec, c.podUID)
	if err != nil {
		return err
	}
	return wrapped.TearDownAt(dir)
}
<commit_msg>remove unused function<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 configmap

import (
	"fmt"

	"github.com/golang/glog"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/types"
	ioutil "k8s.io/kubernetes/pkg/util/io"
	"k8s.io/kubernetes/pkg/util/mount"
	"k8s.io/kubernetes/pkg/util/strings"
	"k8s.io/kubernetes/pkg/volume"
	volumeutil "k8s.io/kubernetes/pkg/volume/util"
)

// ProbeVolumePlugin is the entry point for plugin detection in a package.
func ProbeVolumePlugins() []volume.VolumePlugin {
	return []volume.VolumePlugin{&configMapPlugin{}}
}

const (
	configMapPluginName = "kubernetes.io/configmap"
)

// configMapPlugin implements the VolumePlugin interface.
type configMapPlugin struct {
	host volume.VolumeHost
}

var _ volume.VolumePlugin = &configMapPlugin{}

func (plugin *configMapPlugin) Init(host volume.VolumeHost) error {
	plugin.host = host
	return nil
}

func (plugin *configMapPlugin) Name() string {
	return configMapPluginName
}

func (plugin *configMapPlugin) CanSupport(spec *volume.Spec) bool {
	return spec.Volume != nil && spec.Volume.ConfigMap != nil
}

func (plugin *configMapPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) {
	return &configMapVolumeBuilder{
		configMapVolume: &configMapVolume{spec.Name(), pod.UID, plugin, plugin.host.GetMounter(), plugin.host.GetWriter(), volume.MetricsNil{}},
		source:          *spec.Volume.ConfigMap,
		pod:             *pod,
		opts:            &opts}, nil
}

func (plugin *configMapPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) {
	return &configMapVolumeCleaner{&configMapVolume{volName, podUID, plugin, plugin.host.GetMounter(), plugin.host.GetWriter(), volume.MetricsNil{}}}, nil
}

type configMapVolume struct {
	volName string
	podUID  types.UID
	plugin  *configMapPlugin
	mounter mount.Interface
	writer  ioutil.Writer
	volume.MetricsNil
}

var _ volume.Volume = &configMapVolume{}

func (sv *configMapVolume) GetPath() string {
	return sv.plugin.host.GetPodVolumeDir(sv.podUID, strings.EscapeQualifiedNameForDisk(configMapPluginName), sv.volName)
}

// configMapVolumeBuilder handles retrieving secrets from the API server
// and placing them into the volume on the host.
type configMapVolumeBuilder struct {
	*configMapVolume

	source api.ConfigMapVolumeSource
	pod    api.Pod
	opts   *volume.VolumeOptions
}

var _ volume.Builder = &configMapVolumeBuilder{}

func (sv *configMapVolume) GetAttributes() volume.Attributes {
	return volume.Attributes{
		ReadOnly:        true,
		Managed:         true,
		SupportsSELinux: true,
	}
}

// This is the spec for the volume that this plugin wraps.
var wrappedVolumeSpec = volume.Spec{
	Volume: &api.Volume{VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageMediumMemory}}},
}

func (b *configMapVolumeBuilder) SetUp(fsGroup *int64) error {
	return b.SetUpAt(b.GetPath(), fsGroup)
}

func (b *configMapVolumeBuilder) SetUpAt(dir string, fsGroup *int64) error {
	glog.V(3).Infof("Setting up volume %v for pod %v at %v", b.volName, b.pod.UID, dir)

	// Wrap EmptyDir, let it do the setup.
	wrapped, err := b.plugin.host.NewWrapperBuilder(b.volName, wrappedVolumeSpec, &b.pod, *b.opts)
	if err != nil {
		return err
	}
	if err := wrapped.SetUpAt(dir, fsGroup); err != nil {
		return err
	}

	kubeClient := b.plugin.host.GetKubeClient()
	if kubeClient == nil {
		return fmt.Errorf("Cannot setup configMap volume %v because kube client is not configured", b.volName)
	}

	configMap, err := kubeClient.Core().ConfigMaps(b.pod.Namespace).Get(b.source.Name)
	if err != nil {
		glog.Errorf("Couldn't get configMap %v/%v: %v", b.pod.Namespace, b.source.Name, err)
		return err
	}

	totalBytes := totalBytes(configMap)
	glog.V(3).Infof("Received configMap %v/%v containing (%v) pieces of data, %v total bytes",
		b.pod.Namespace,
		b.source.Name,
		len(configMap.Data),
		totalBytes)

	payload, err := makePayload(b.source.Items, configMap)
	if err != nil {
		return err
	}

	writerContext := fmt.Sprintf("pod %v/%v volume %v", b.pod.Namespace, b.pod.Name, b.volName)
	writer, err := volumeutil.NewAtomicWriter(dir, writerContext)
	if err != nil {
		glog.Errorf("Error creating atomic writer: %v", err)
		return err
	}

	err = writer.Write(payload)
	if err != nil {
		glog.Errorf("Error writing payload to dir: %v", err)
		return err
	}

	err = volume.SetVolumeOwnership(b, fsGroup)
	if err != nil {
		glog.Errorf("Error applying volume ownership settings for group: %v", fsGroup)
		return err
	}

	return nil
}

func makePayload(mappings []api.KeyToPath, configMap *api.ConfigMap) (map[string][]byte, error) {
	payload := make(map[string][]byte, len(configMap.Data))

	if len(mappings) == 0 {
		for name, data := range configMap.Data {
			payload[name] = []byte(data)
		}
	} else {
		for _, ktp := range mappings {
			content, ok := configMap.Data[ktp.Key]
			if !ok {
				glog.Errorf("references non-existent config key")
				return nil, fmt.Errorf("references non-existent config key")
			}

			payload[ktp.Path] = []byte(content)
		}
	}

	return payload, nil
}

func totalBytes(configMap *api.ConfigMap) int {
	totalSize := 0
	for _, value := range configMap.Data {
		totalSize += len(value)
	}

	return totalSize
}

// configMapVolumeCleaner handles cleaning up configMap volumes.
type configMapVolumeCleaner struct {
	*configMapVolume
}

var _ volume.Cleaner = &configMapVolumeCleaner{}

func (c *configMapVolumeCleaner) TearDown() error {
	return c.TearDownAt(c.GetPath())
}

func (c *configMapVolumeCleaner) TearDownAt(dir string) error {
	glog.V(3).Infof("Tearing down volume %v for pod %v at %v", c.volName, c.podUID, dir)

	// Wrap EmptyDir, let it do the teardown.
	wrapped, err := c.plugin.host.NewWrapperCleaner(c.volName, wrappedVolumeSpec, c.podUID)
	if err != nil {
		return err
	}
	return wrapped.TearDownAt(dir)
}
<|endoftext|>


<commit_before>package volume

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/nu7hatch/gouuid"
	"github.com/pivotal-golang/lager"
)

type Strategy map[string]string

const (
	StrategyEmpty       = "empty"
	StrategyCopyOnWrite = "cow"
	propertiesFileName  = "properties.json"
)

type Volume struct {
	GUID       string     `json:"guid"`
	Path       string     `json:"path"`
	Properties Properties `json:"properties"`
}

type Volumes []Volume

var ErrMissingStrategy = errors.New("missing strategy")
var ErrUnrecognizedStrategy = errors.New("unrecognized strategy")
var ErrCreateVolumeFailed = errors.New("failed to create volume")
var ErrSetPropertyFailed = errors.New("failed to set property on volume")
var ErrListVolumesFailed = errors.New("failed to list volumes")
var ErrNoParentVolumeProvided = errors.New("no parent volume provided")
var ErrParentVolumeNotFound = errors.New("parent volume not found")

type Repository struct {
	volumeDir string
	driver    Driver

	logger lager.Logger
}

func NewRepository(logger lager.Logger, volumeDir string, driver Driver) *Repository {
	return &Repository{
		volumeDir: volumeDir,
		logger:    logger,
		driver:    driver,
	}
}

type Driver interface {
	CreateVolume(path string) error
	CreateCopyOnWriteLayer(path string, parent string) error
}

func (repo *Repository) CreateVolume(strategy Strategy, properties Properties) (Volume, error) {
	strategyName, found := strategy["type"]
	if !found {
		return Volume{}, ErrMissingStrategy
	}

	logger := repo.logger.Session("create-volume", lager.Data{
		"strategy": strategyName,
	})

	guid := repo.createUuid()
	newVolumeMetadataPath := repo.metadataPath(guid)
	err := os.Mkdir(newVolumeMetadataPath, 0755)
	if err != nil {
		return repo.handleError(err, "failed-to-create-metadata-dir", ErrCreateVolumeFailed)
	}

	propertiesBytes, err := json.Marshal(properties)
	if err != nil {
		return repo.handleError(err, "failed-to-marshal-properties", ErrCreateVolumeFailed)
	}

	err = ioutil.WriteFile(repo.propertiesPath(guid), propertiesBytes, 0644)
	if err != nil {
		return repo.handleError(err, "failed-to-write-properties", ErrCreateVolumeFailed)
	}

	newVolumeDataPath := repo.dataPath(guid)
	err = repo.doStrategy(strategyName, newVolumeDataPath, strategy, logger)
	if err != nil {
		repo.deleteVolumeMetadataDir(guid)
		return Volume{}, err
	}

	return Volume{
		Path:       newVolumeDataPath,
		GUID:       guid,
		Properties: properties,
	}, nil
}

func (repo *Repository) handleError(internalError error, errorMsg string, externalError error) (Volume, error) {
	repo.logger.Error(errorMsg, internalError)
	return Volume{}, externalError
}

func (repo *Repository) ListVolumes(queryProperties Properties) (Volumes, error) {
	volumes, err := ioutil.ReadDir(repo.volumeDir)
	if err != nil {
		repo.logger.Error("failed-to-list-dirs", err, lager.Data{
			"volume-dir": repo.volumeDir,
		})

		return Volumes{}, ErrListVolumesFailed
	}

	response := make(Volumes, 0, len(volumes))
	for _, volume := range volumes {
		propertiesPath := repo.propertiesPath(volume.Name())
		propBytes, err := ioutil.ReadFile(propertiesPath)
		if err != nil {
			repo.logger.Error("failed-to-read-properties", err, lager.Data{
				"volume": volume.Name(),
			})
			return nil, err
		}

		var properties Properties
		err = json.Unmarshal(propBytes, &properties)
		if err != nil {
			repo.logger.Error("failed-to-unmarshal-properties", err, lager.Data{
				"volume": volume.Name(),
			})
			return nil, err
		}

		if properties.HasProperties(queryProperties) {
			response = append(response, Volume{
				GUID:       volume.Name(),
				Path:       repo.dataPath(volume.Name()),
				Properties: properties,
			})
		}
	}

	return response, nil
}

func (repo *Repository) SetProperty(volumeGUID string, propertyName string, propertyValue string) error {
	propertiesPath := repo.propertiesPath(volumeGUID)

	propBytes, err := ioutil.ReadFile(propertiesPath)
	if err != nil {
		_, err = repo.handleError(err, "failed-to-read-properties-file", ErrSetPropertyFailed)
		return err
	}

	var properties Properties
	err = json.Unmarshal(propBytes, &properties)
	if err != nil {
		repo.logger.Error("failed-to-unmarshal-properties", err, lager.Data{
			"volume": volumeGUID,
		})
		return err
	}

	properties[propertyName] = propertyValue

	propertiesBytes, err := json.Marshal(properties)
	if err != nil {
		_, err = repo.handleError(err, "failed-to-marshal-properties", ErrSetPropertyFailed)
		return err
	}

	err = ioutil.WriteFile(repo.propertiesPath(volumeGUID), propertiesBytes, 0644)
	if err != nil {
		_, err = repo.handleError(err, "failed-to-write-properties", ErrSetPropertyFailed)
		return err
	}

	return nil
}

func (repo *Repository) doStrategy(strategyName string, newVolumeDataPath string, strategy Strategy, logger lager.Logger) error {
	switch strategyName {
	case StrategyEmpty:
		err := repo.createEmptyVolume(newVolumeDataPath)
		if err != nil {
			logger.Error("failed-to-create-volume", err, lager.Data{
				"path": newVolumeDataPath,
			})
			return ErrCreateVolumeFailed
		}

	case StrategyCopyOnWrite:
		parentGUID, found := strategy["volume"]
		if !found {
			logger.Error("no-parent-volume-provided", nil)
			return ErrNoParentVolumeProvided
		}

		if !repo.volumeExists(parentGUID) {
			logger.Error("parent-volume-not-found", nil)
			return ErrParentVolumeNotFound
		}

		parentDataPath := repo.dataPath(parentGUID)
		err := repo.createCowVolume(parentDataPath, newVolumeDataPath)
		if err != nil {
			logger.Error("failed-to-copy-volume", err)
			return ErrCreateVolumeFailed
		}

	default:
		logger.Error("unrecognized-strategy", nil, lager.Data{
			"strategy": strategyName,
		})
		return ErrUnrecognizedStrategy
	}

	return nil
}

func (repo *Repository) metadataPath(id string) string {
	return filepath.Join(repo.volumeDir, id)
}

func (repo *Repository) propertiesPath(id string) string {
	return filepath.Join(repo.metadataPath(id), propertiesFileName)
}

func (repo *Repository) dataPath(id string) string {
	return filepath.Join(repo.metadataPath(id), "volume")
}

func (repo *Repository) deleteVolumeMetadataDir(id string) {
	err := os.RemoveAll(repo.metadataPath(id))
	if err != nil {
		repo.logger.Error("failed-to-cleanup", err, lager.Data{
			"guid": id,
		})
	}
}

func (repo *Repository) createEmptyVolume(volumePath string) error {
	err := repo.driver.CreateVolume(volumePath)
	if err != nil {
		return err
	}

	return nil
}

func (repo *Repository) createCowVolume(parentPath string, newPath string) error {
	err := repo.driver.CreateCopyOnWriteLayer(newPath, parentPath)
	if err != nil {
		return err
	}

	return nil
}

func (repo *Repository) createUuid() string {
	guid, err := uuid.NewV4()
	if err != nil {
		repo.logger.Fatal("failed-to-generate-guid", err)
	}

	return guid.String()
}

func (repo *Repository) volumeExists(guid string) bool {
	info, err := os.Stat(repo.metadataPath(guid))
	if err != nil {
		return false
	}

	return info.IsDir()
}
<commit_msg>extract properties file code into object<commit_after>package volume

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/nu7hatch/gouuid"
	"github.com/pivotal-golang/lager"
)

type Strategy map[string]string

const (
	StrategyEmpty       = "empty"
	StrategyCopyOnWrite = "cow"

	propertiesFileName = "properties.json"
)

type Volume struct {
	GUID       string     `json:"guid"`
	Path       string     `json:"path"`
	Properties Properties `json:"properties"`
}

type Volumes []Volume

var ErrMissingStrategy = errors.New("missing strategy")
var ErrUnrecognizedStrategy = errors.New("unrecognized strategy")
var ErrCreateVolumeFailed = errors.New("failed to create volume")
var ErrSetPropertyFailed = errors.New("failed to set property on volume")
var ErrListVolumesFailed = errors.New("failed to list volumes")
var ErrNoParentVolumeProvided = errors.New("no parent volume provided")
var ErrParentVolumeNotFound = errors.New("parent volume not found")

type Repository struct {
	volumeDir string
	driver    Driver

	logger lager.Logger
}

type propertiesFile struct {
	path string
}

func (pf *propertiesFile) WriteProperties(properties Properties) error {
	file, err := os.OpenFile(
		pf.path,
		os.O_WRONLY|os.O_CREATE,
		0644,
	)
	if err != nil {
		return err
	}
	defer file.Close()

	return json.NewEncoder(file).Encode(properties)
}

func (pf *propertiesFile) Properties() (Properties, error) {
	var properties Properties

	file, err := os.Open(pf.path)
	if err != nil {
		return Properties{}, err
	}
	defer file.Close()

	if err := json.NewDecoder(file).Decode(&properties); err != nil {
		return Properties{}, err
	}

	return properties, nil
}

func NewRepository(logger lager.Logger, volumeDir string, driver Driver) *Repository {
	return &Repository{
		volumeDir: volumeDir,
		logger:    logger,
		driver:    driver,
	}
}

type Driver interface {
	CreateVolume(path string) error
	CreateCopyOnWriteLayer(path string, parent string) error
}

func (repo *Repository) CreateVolume(strategy Strategy, properties Properties) (Volume, error) {
	strategyName, found := strategy["type"]
	if !found {
		return Volume{}, ErrMissingStrategy
	}

	logger := repo.logger.Session("create-volume", lager.Data{
		"strategy": strategyName,
	})

	guid := repo.createUuid()
	newVolumeMetadataPath := repo.metadataPath(guid)
	err := os.Mkdir(newVolumeMetadataPath, 0755)
	if err != nil {
		return repo.handleError(err, "failed-to-create-metadata-dir", ErrCreateVolumeFailed)
	}

	err = repo.propertiesFile(guid).WriteProperties(properties)
	if err != nil {
		return repo.handleError(err, "failed-to-create-properties-file", ErrCreateVolumeFailed)
	}

	newVolumeDataPath := repo.dataPath(guid)
	err = repo.doStrategy(strategyName, newVolumeDataPath, strategy, logger)
	if err != nil {
		repo.deleteVolumeMetadataDir(guid)
		return Volume{}, err
	}

	return Volume{
		Path:       newVolumeDataPath,
		GUID:       guid,
		Properties: properties,
	}, nil
}

func (repo *Repository) handleError(internalError error, errorMsg string, externalError error) (Volume, error) {
	repo.logger.Error(errorMsg, internalError)
	return Volume{}, externalError
}

func (repo *Repository) ListVolumes(queryProperties Properties) (Volumes, error) {
	volumeDirs, err := ioutil.ReadDir(repo.volumeDir)
	if err != nil {
		repo.logger.Error("failed-to-list-dirs", err, lager.Data{
			"volume-dir": repo.volumeDir,
		})

		return Volumes{}, ErrListVolumesFailed
	}

	response := make(Volumes, 0, len(volumeDirs))

	for _, volumeDir := range volumeDirs {
		volumeProperties, err := repo.propertiesFile(volumeDir.Name()).Properties()
		if err != nil {
			repo.logger.Error("failed-to-read-properties", err, lager.Data{
				"volume": volumeDir.Name(),
			})
			return nil, err
		}

		if volumeProperties.HasProperties(queryProperties) {
			response = append(response, Volume{
				GUID:       volumeDir.Name(),
				Path:       repo.dataPath(volumeDir.Name()),
				Properties: volumeProperties,
			})
		}
	}

	return response, nil
}

func (repo *Repository) SetProperty(volumeGUID string, propertyName string, propertyValue string) error {
	pf := repo.propertiesFile(volumeGUID)

	properties, err := pf.Properties()
	if err != nil {
		repo.logger.Error("failed-to-read-properties", err, lager.Data{
			"volume": volumeGUID,
		})
		return err
	}

	properties[propertyName] = propertyValue

	err = pf.WriteProperties(properties)
	if err != nil {
		_, err = repo.handleError(err, "failed-to-write-properties", ErrSetPropertyFailed)
		return err
	}

	return nil
}

func (repo *Repository) doStrategy(strategyName string, newVolumeDataPath string, strategy Strategy, logger lager.Logger) error {
	switch strategyName {
	case StrategyEmpty:
		err := repo.createEmptyVolume(newVolumeDataPath)
		if err != nil {
			logger.Error("failed-to-create-volume", err, lager.Data{
				"path": newVolumeDataPath,
			})
			return ErrCreateVolumeFailed
		}

	case StrategyCopyOnWrite:
		parentGUID, found := strategy["volume"]
		if !found {
			logger.Error("no-parent-volume-provided", nil)
			return ErrNoParentVolumeProvided
		}

		if !repo.volumeExists(parentGUID) {
			logger.Error("parent-volume-not-found", nil)
			return ErrParentVolumeNotFound
		}

		parentDataPath := repo.dataPath(parentGUID)
		err := repo.createCowVolume(parentDataPath, newVolumeDataPath)
		if err != nil {
			logger.Error("failed-to-copy-volume", err)
			return ErrCreateVolumeFailed
		}

	default:
		logger.Error("unrecognized-strategy", nil, lager.Data{
			"strategy": strategyName,
		})
		return ErrUnrecognizedStrategy
	}

	return nil
}

func (repo *Repository) metadataPath(id string) string {
	return filepath.Join(repo.volumeDir, id)
}

func (repo *Repository) propertiesPath(id string) string {
	return filepath.Join(repo.metadataPath(id), propertiesFileName)
}

func (repo *Repository) propertiesFile(id string) *propertiesFile {
	return &propertiesFile{path: repo.propertiesPath(id)}
}

func (repo *Repository) dataPath(id string) string {
	return filepath.Join(repo.metadataPath(id), "volume")
}

func (repo *Repository) deleteVolumeMetadataDir(id string) {
	err := os.RemoveAll(repo.metadataPath(id))
	if err != nil {
		repo.logger.Error("failed-to-cleanup", err, lager.Data{
			"guid": id,
		})
	}
}

func (repo *Repository) createEmptyVolume(volumePath string) error {
	err := repo.driver.CreateVolume(volumePath)
	if err != nil {
		return err
	}

	return nil
}

func (repo *Repository) createCowVolume(parentPath string, newPath string) error {
	err := repo.driver.CreateCopyOnWriteLayer(newPath, parentPath)
	if err != nil {
		return err
	}

	return nil
}

func (repo *Repository) createUuid() string {
	guid, err := uuid.NewV4()
	if err != nil {
		repo.logger.Fatal("failed-to-generate-guid", err)
	}

	return guid.String()
}

func (repo *Repository) volumeExists(guid string) bool {
	info, err := os.Stat(repo.metadataPath(guid))
	if err != nil {
		return false
	}

	return info.IsDir()
}
<|endoftext|>


<commit_before>package async

import (
	"errors"
	"fmt"
	"sync"
	"time"
)

const Unlimit = 0

type Method func(args ...interface{}) (interface{}, error)
type LambdaMethod func() (interface{}, error)

var panicHandler func(interface{})

func SetPanicHandler(hanlder func(interface{})) {
	panicHandler = hanlder
}

func Safety(method func() (interface{}, error)) (res interface{}, err error) {
	defer func() {
		if e := recover(); e != nil {
			_, ok := e.(error)
			if ok {
				err = e.(error)
			} else {
				err = errors.New(fmt.Sprintf("%v", e))
			}
			if panicHandler != nil {
				panicHandler(err)
			}
		}
	}()
	return method()
}

func Retry(method func()(interface{}, error), maxCount int, interval time.Duration) (interface{}, error) {
	count := 0
	for {
		res, err := Lambda(method, Unlimit)
		if err == nil {
			return res, err
		}
		count = count + 1
		if count >= maxCount {
			return nil, err
		}
		<-time.After(interval)
	}
}

func Lambda(method func() (interface{}, error), timeout time.Duration) (interface{}, error) {
	output := make(chan interface{})
	go func() {
		defer close(output)
		defer func() {
			if e := recover(); e != nil {
				err := errors.New(fmt.Sprintf("%s", e))
				if panicHandler != nil {
					panicHandler(err)
				}
				output <- err
			}
		}()
		res, err := method()
		if err != nil {
			output <- err
		} else {
			output <- res
		}
	}()
	if timeout > 0 {
		timer := time.NewTimer(timeout)
		defer timer.Stop()
		select {
		case res := <-output:
			{
				switch err := res.(type) {
				case error:
					{
						return nil, err
					}
				default:
					{
						return res, nil
					}
				}
			}
		case <-timer.C:
			{
				return nil, errors.New("Async_Timeout")
			}
		}
	} else {
		res := <-output
		switch err := res.(type) {
		case error:
			{
				return nil, err
			}
		default:
			{
				return res, nil
			}
		}
	}
}

func Call(m Method, timeout time.Duration, args ...interface{}) (interface{}, error) {
	return Lambda(func() (interface{}, error) {
		return m(args...)
	}, timeout)
}

func All(methods []LambdaMethod, timeout time.Duration) []interface{} {
	var wg sync.WaitGroup
	result := make([]interface{}, len(methods))
	for i, m := range methods {
		wg.Add(1)
		go func(index int, method LambdaMethod) {
			defer wg.Done()
			res, err := Lambda(method, timeout)
			if err != nil {
				result[index] = err
			} else {
				result[index] = res
			}
		}(i, m)
	}
	wg.Wait()
	return result
}

func Serise(methods []LambdaMethod, timeout time.Duration) []interface{} {
	result := make([]interface{}, 0)
	for _, m := range methods {
		res, err := Lambda(m, timeout)
		if err != nil {
			result = append(result, err)
			return result
		} else {
			result = append(result, res)
		}
	}
	return result
}

func Flow(enter Method, args []interface{}, methods []Method, timeout time.Duration) (interface{}, error) {
	var (
		res interface{}
		err error
	)
	res, err = Call(enter, timeout, args...)
	if err != nil {
		return nil, err
	}
	for _, m := range methods {
		res, err = Call(m, timeout, res)
		if err != nil {
			return nil, err
		}
	}
	return res, nil
}

func Any(methods []LambdaMethod, timeout time.Duration) ([]interface{}, error) {
	resChan := make(chan []interface{}, 1)
	errChan := make(chan error, len(methods))
	go func() {
		defer func() {
			close(resChan)
			close(errChan)
		}()
		var wg sync.WaitGroup
		result := make([]interface{}, len(methods))
		for i, m := range methods {
			wg.Add(1)
			go func(index int, method LambdaMethod) {
				defer wg.Done()
				res, err := Lambda(method, timeout)
				if err != nil {
					errChan <- err
				} else {
					result[index] = res
				}
			}(i, m)
		}
		wg.Wait()
		resChan <- result
	}()
	select {
	case err := <-errChan:
		return nil, err
	case res := <-resChan:
		return res, nil
	}
}

func AnyOne(methods []LambdaMethod, timeout time.Duration) (interface{}, []error) {
	resChan := make(chan interface{}, len(methods))
	errChan := make(chan []error)
	go func() {
		defer func() {
			close(resChan)
			close(errChan)
		}()
		var wg sync.WaitGroup
		errs := make([]error, len(methods))
		for i, m := range methods {
			wg.Add(1)
			go func(index int, method LambdaMethod) {
				defer wg.Done()
				res, err := Lambda(method, timeout)
				if err != nil {
					errs[index] = err
				} else {
					resChan <- res
				}
			}(i, m)
		}
		wg.Wait()
		errChan <- errs
	}()
	select {
	case errs := <-errChan:
		return nil, errs
	case res := <-resChan:
		return res, nil
	}
}

func Parallel(methods []LambdaMethod, maxCount int) []interface{} {
	if maxCount == Unlimit {
		maxCount = 64
	}
	var wg sync.WaitGroup
	workers := make(chan bool, maxCount)
	for i := 0; i < maxCount; i++ {
		workers <- true
	}
	results := make([]interface{}, len(methods))
	for index, method := range methods {
		<-workers
		wg.Add(1)
		go func(i int, m LambdaMethod) {
			defer func() {
				workers <- true
				wg.Done()
			}()
			res, err := Lambda(m, 0)
			if err != nil {
				results[i] = err
			} else {
				results[i] = res
			}
		}(index, method)
	}
	wg.Wait()
	close(workers)
	return results
}

func Foreach(objs []interface{}, method func(int) (interface{}, error), maxCount int) []interface{} {
	if maxCount == Unlimit {
		maxCount = 64
	}
	var wg sync.WaitGroup
	workers := make(chan bool, maxCount)
	for i := 0; i < maxCount; i++ {
		workers <- true
	}
	results := make([]interface{}, len(objs))
	for index, _ := range objs {
		<-workers
		wg.Add(1)
		go func(i int, method func(int) (interface{}, error)) {
			defer func() {
				workers <- true
				wg.Done()
			}()
			res, err := method(i)
			if err != nil {
				results[i] = err
			} else {
				results[i] = res
			}
		}(index, method)
	}
	wg.Wait()
	close(workers)
	return results
}<commit_msg>update code, fix bug<commit_after>package async

import (
	"errors"
	"fmt"
	"sync"
	"time"
)

const Unlimit = 0

type Method func(args ...interface{}) (interface{}, error)
type LambdaMethod func() (interface{}, error)

var panicHandler func(interface{})

func SetPanicHandler(hanlder func(interface{})) {
	panicHandler = hanlder
}

func Safety(method func() (interface{}, error)) (res interface{}, err error) {
	defer func() {
		if e := recover(); e != nil {
			_, ok := e.(error)
			if ok {
				err = e.(error)
			} else {
				err = errors.New(fmt.Sprintf("%v", e))
			}
			if panicHandler != nil {
				panicHandler(err)
			}
		}
	}()
	return method()
}

func Retry(method func()(interface{}, error), maxCount int, interval time.Duration) (interface{}, error) {
	count := 0
	for {
		res, err := Lambda(method, Unlimit)
		if err == nil {
			return res, err
		}
		count = count + 1
		if count >= maxCount {
			return nil, err
		}
		<-time.After(interval)
	}
}

func Lambda(method func() (interface{}, error), timeout time.Duration) (interface{}, error) {
	output := make(chan interface{})
	go func() {
		defer close(output)
		defer func() {
			if e := recover(); e != nil {
				err := errors.New(fmt.Sprintf("%s", e))
				if panicHandler != nil {
					panicHandler(err)
				}
				output <- err
			}
		}()
		res, err := method()
		if err != nil {
			output <- err
		} else {
			output <- res
		}
	}()
	if timeout > 0 {
		timer := time.NewTimer(timeout)
		defer timer.Stop()
		select {
		case res := <-output:
			{
				switch err := res.(type) {
				case error:
					{
						return nil, err
					}
				default:
					{
						return res, nil
					}
				}
			}
		case <-timer.C:
			{
				return nil, errors.New("Async_Timeout")
			}
		}
	} else {
		res := <-output
		switch err := res.(type) {
		case error:
			{
				return nil, err
			}
		default:
			{
				return res, nil
			}
		}
	}
}

func Call(m Method, timeout time.Duration, args ...interface{}) (interface{}, error) {
	return Lambda(func() (interface{}, error) {
		return m(args...)
	}, timeout)
}

func All(methods []LambdaMethod, timeout time.Duration) []interface{} {
	var wg sync.WaitGroup
	result := make([]interface{}, len(methods))
	for i, m := range methods {
		wg.Add(1)
		go func(index int, method LambdaMethod) {
			defer wg.Done()
			res, err := Lambda(method, timeout)
			if err != nil {
				result[index] = err
			} else {
				result[index] = res
			}
		}(i, m)
	}
	wg.Wait()
	return result
}

func Serise(methods []LambdaMethod, timeout time.Duration) []interface{} {
	result := make([]interface{}, 0)
	for _, m := range methods {
		res, err := Lambda(m, timeout)
		if err != nil {
			result = append(result, err)
			return result
		} else {
			result = append(result, res)
		}
	}
	return result
}

func Flow(enter Method, args []interface{}, methods []Method, timeout time.Duration) (interface{}, error) {
	var (
		res interface{}
		err error
	)
	res, err = Call(enter, timeout, args...)
	if err != nil {
		return nil, err
	}
	for _, m := range methods {
		res, err = Call(m, timeout, res)
		if err != nil {
			return nil, err
		}
	}
	return res, nil
}

func Any(methods []LambdaMethod, timeout time.Duration) ([]interface{}, error) {
	resChan := make(chan []interface{}, 1)
	errChan := make(chan error, len(methods))
	go func() {
		defer func() {
			close(resChan)
			close(errChan)
		}()
		var wg sync.WaitGroup
		result := make([]interface{}, len(methods))
		for i, m := range methods {
			wg.Add(1)
			go func(index int, method LambdaMethod) {
				defer wg.Done()
				res, err := Lambda(method, timeout)
				if err != nil {
					errChan <- err
				} else {
					result[index] = res
				}
			}(i, m)
		}
		wg.Wait()
		resChan <- result
	}()
	select {
	case err := <-errChan:
		return nil, err
	case res := <-resChan:
		return res, nil
	}
}

func AnyOne(methods []LambdaMethod, timeout time.Duration) (interface{}, []error) {
	resChan := make(chan interface{}, len(methods))
	errChan := make(chan []error)
	go func() {
		defer func() {
			close(resChan)
			close(errChan)
		}()
		var wg sync.WaitGroup
		errs := make([]error, len(methods))
		for i, m := range methods {
			wg.Add(1)
			go func(index int, method LambdaMethod) {
				defer wg.Done()
				res, err := Lambda(method, timeout)
				if err != nil {
					errs[index] = err
				} else {
					resChan <- res
				}
			}(i, m)
		}
		wg.Wait()
		errChan <- errs
	}()
	select {
	case errs := <-errChan:
		return nil, errs
	case res := <-resChan:
		return res, nil
	}
}

func Parallel(methods []LambdaMethod, maxCount int) []interface{} {
	if maxCount == Unlimit {
		maxCount = 64
	}
	var wg sync.WaitGroup
	workers := make(chan bool, maxCount)
	for i := 0; i < maxCount; i++ {
		workers <- true
	}
	results := make([]interface{}, len(methods))
	for index, method := range methods {
		<-workers
		wg.Add(1)
		go func(i int, m LambdaMethod) {
			defer func() {
				workers <- true
				wg.Done()
			}()
			res, err := Lambda(m, 0)
			if err != nil {
				results[i] = err
			} else {
				results[i] = res
			}
		}(index, method)
	}
	wg.Wait()
	close(workers)
	return results
}

func Foreach(objs []interface{}, method func(int) (interface{}, error), maxCount int) []interface{} {
	if maxCount == Unlimit {
		maxCount = 64
	}
	var wg sync.WaitGroup
	workers := make(chan bool, maxCount)
	for i := 0; i < maxCount; i++ {
		workers <- true
	}
	results := make([]interface{}, len(objs))
	for index, _ := range objs {
		<-workers
		wg.Add(1)
		go func(i int, method func(int) (interface{}, error)) {
			defer func() {
				workers <- true
				wg.Done()
			}()
			res, err := Safety(func()(interface{}, error) {
				return method(i)
			})
			if err != nil {
				results[i] = err
			} else {
				results[i] = res
			}
		}(index, method)
	}
	wg.Wait()
	close(workers)
	return results
}<|endoftext|>


<commit_before>package captcha

import (
	"bytes"
	"encoding/binary"
	"math"
	"os"
	"rand"
	"io"
)

const sampleRate = 8000 // Hz

var (
	longestDigitSndLen int
	endingBeepSound    []byte
	reverseDigitSounds [][]byte
)

func init() {
	for _, v := range digitSounds {
		if longestDigitSndLen < len(v) {
			longestDigitSndLen = len(v)
		}
	}
	endingBeepSound = changeSpeed(beepSound, 1.4)
	// Preallocate reversed digit sounds for background noise.
	reverseDigitSounds = make([][]byte, len(digitSounds))
	for i, v := range digitSounds {
		reverseDigitSounds[i] = reversedSound(v)
	}
}

// BUG(dchest): [Not our bug] Google Chrome 10 plays unsigned 8-bit PCM WAVE
// audio on Mac with horrible distortions.  Issue:
// http://code.google.com/p/chromium/issues/detail?id=70730.
// This has been fixed, and version 12 will play them properly.

type Audio struct {
	body *bytes.Buffer
}

// NewImage returns a new audio captcha with the given digits, where each digit
// must be in range 0-9.
func NewAudio(digits []byte) *Audio {
	numsnd := make([][]byte, len(digits))
	nsdur := 0
	for i, n := range digits {
		snd := randomizedDigitSound(n)
		nsdur += len(snd)
		numsnd[i] = snd
	}
	// Random intervals between digits (including beginning).
	intervals := make([]int, len(digits)+1)
	intdur := 0
	for i := range intervals {
		dur := rnd(sampleRate, sampleRate*3) // 1 to 3 seconds
		intdur += dur
		intervals[i] = dur
	}
	// Generate background sound.
	bg := makeBackgroundSound(longestDigitSndLen*len(digits) + intdur)
	// Create buffer and write audio to it.
	a := new(Audio)
	sil := makeSilence(sampleRate / 5)
	bufcap := 3*len(beepSound) + 2*len(sil) + len(bg) + len(endingBeepSound)
	a.body = bytes.NewBuffer(make([]byte, 0, bufcap))
	// Write prelude, three beeps.
	a.body.Write(beepSound)
	a.body.Write(sil)
	a.body.Write(beepSound)
	a.body.Write(sil)
	a.body.Write(beepSound)
	// Write digits.
	pos := intervals[0]
	for i, v := range numsnd {
		mixSound(bg[pos:], v)
		pos += len(v) + intervals[i+1]
	}
	a.body.Write(bg)
	// Write ending (one beep).
	a.body.Write(endingBeepSound)
	return a
}

// WriteTo writes captcha audio in WAVE format into the given io.Writer, and
// returns the number of bytes written and an error if any.
func (a *Audio) WriteTo(w io.Writer) (n int64, err os.Error) {
	nn, err := w.Write(waveHeader)
	n = int64(nn)
	if err != nil {
		return
	}
	err = binary.Write(w, binary.LittleEndian, uint32(a.body.Len()))
	if err != nil {
		return
	}
	nn += 4
	n, err = a.body.WriteTo(w)
	n += int64(nn)
	return
}

// EncodedLen returns the length of WAV-encoded audio captcha.
func (a *Audio) EncodedLen() int {
	return len(waveHeader) + 4 + a.body.Len()
}

// mixSound mixes src into dst. Dst must have length equal to or greater than
// src length.
func mixSound(dst, src []byte) {
	for i, v := range src {
		av := int(v)
		bv := int(dst[i])
		if av < 128 && bv < 128 {
			dst[i] = byte(av * bv / 128)
		} else {
			dst[i] = byte(2*(av+bv) - av*bv/128 - 256)
		}
	}
}

func setSoundLevel(a []byte, level float64) {
	for i, v := range a {
		av := float64(v)
		switch {
		case av > 128:
			if av = (av-128)*level + 128; av < 128 {
				av = 128
			}
		case av < 128:
			if av = 128 - (128-av)*level; av > 128 {
				av = 128
			}
		default:
			continue
		}
		a[i] = byte(av)
	}
}

// changeSpeed returns new PCM bytes from the bytes with the speed and pitch
// changed to the given value that must be in range [0, x].
func changeSpeed(a []byte, speed float64) []byte {
	b := make([]byte, int(math.Floor(float64(len(a))*speed)))
	var p float64
	for _, v := range a {
		for i := int(p); i < int(p+speed); i++ {
			b[i] = v
		}
		p += speed
	}
	return b
}

func randomSpeed(a []byte) []byte {
	pitch := rndf(0.9, 1.2)
	return changeSpeed(a, pitch)
}

func makeSilence(length int) []byte {
	b := make([]byte, length)
	for i := range b {
		b[i] = 128
	}
	return b
}

func makeWhiteNoise(length int, level uint8) []byte {
	noise := randomBytes(length)
	adj := 128 - level/2
	for i, v := range noise {
		v %= level
		v += adj
		noise[i] = v
	}
	return noise
}

func reversedSound(a []byte) []byte {
	n := len(a)
	b := make([]byte, n)
	for i, v := range a {
		b[n-1-i] = v
	}
	return b
}

func makeBackgroundSound(length int) []byte {
	b := makeWhiteNoise(length, 4)
	for i := 0; i < length/(sampleRate/10); i++ {
		snd := reverseDigitSounds[rand.Intn(10)]
		snd = changeSpeed(snd, rndf(0.8, 1.4))
		place := rand.Intn(len(b) - len(snd))
		setSoundLevel(snd, rndf(0.2, 0.3))
		mixSound(b[place:], snd)
	}
	return b
}

func randomizedDigitSound(n byte) []byte {
	s := randomSpeed(digitSounds[n])
	setSoundLevel(s, rndf(0.7, 1.3))
	return s
}
<commit_msg>audio: write pad byte when data length is odd.<commit_after>package captcha

import (
	"bytes"
	"encoding/binary"
	"math"
	"os"
	"rand"
	"io"
)

const sampleRate = 8000 // Hz

var (
	longestDigitSndLen int
	endingBeepSound    []byte
	reverseDigitSounds [][]byte
)

func init() {
	for _, v := range digitSounds {
		if longestDigitSndLen < len(v) {
			longestDigitSndLen = len(v)
		}
	}
	endingBeepSound = changeSpeed(beepSound, 1.4)
	// Preallocate reversed digit sounds for background noise.
	reverseDigitSounds = make([][]byte, len(digitSounds))
	for i, v := range digitSounds {
		reverseDigitSounds[i] = reversedSound(v)
	}
}

// BUG(dchest): [Not our bug] Google Chrome 10 plays unsigned 8-bit PCM WAVE
// audio on Mac with horrible distortions.  Issue:
// http://code.google.com/p/chromium/issues/detail?id=70730.
// This has been fixed, and version 12 will play them properly.

type Audio struct {
	body *bytes.Buffer
}

// NewImage returns a new audio captcha with the given digits, where each digit
// must be in range 0-9.
func NewAudio(digits []byte) *Audio {
	numsnd := make([][]byte, len(digits))
	nsdur := 0
	for i, n := range digits {
		snd := randomizedDigitSound(n)
		nsdur += len(snd)
		numsnd[i] = snd
	}
	// Random intervals between digits (including beginning).
	intervals := make([]int, len(digits)+1)
	intdur := 0
	for i := range intervals {
		dur := rnd(sampleRate, sampleRate*3) // 1 to 3 seconds
		intdur += dur
		intervals[i] = dur
	}
	// Generate background sound.
	bg := makeBackgroundSound(longestDigitSndLen*len(digits) + intdur)
	// Create buffer and write audio to it.
	a := new(Audio)
	sil := makeSilence(sampleRate / 5)
	bufcap := 3*len(beepSound) + 2*len(sil) + len(bg) + len(endingBeepSound)
	a.body = bytes.NewBuffer(make([]byte, 0, bufcap))
	// Write prelude, three beeps.
	a.body.Write(beepSound)
	a.body.Write(sil)
	a.body.Write(beepSound)
	a.body.Write(sil)
	a.body.Write(beepSound)
	// Write digits.
	pos := intervals[0]
	for i, v := range numsnd {
		mixSound(bg[pos:], v)
		pos += len(v) + intervals[i+1]
	}
	a.body.Write(bg)
	// Write ending (one beep).
	a.body.Write(endingBeepSound)
	return a
}

// WriteTo writes captcha audio in WAVE format into the given io.Writer, and
// returns the number of bytes written and an error if any.
func (a *Audio) WriteTo(w io.Writer) (n int64, err os.Error) {
	// Header.
	nn, err := w.Write(waveHeader)
	n = int64(nn)
	if err != nil {
		return
	}
	// Chunk length.
	err = binary.Write(w, binary.LittleEndian, uint32(a.body.Len()))
	if err != nil {
		return
	}
	nn += 4
	// Chunk data.
	n, err = a.body.WriteTo(w)
	n += int64(nn)
	// Pad byte if chunk length is odd.
	// (As header has even length, we can check if n is odd, not chunk).
	if n % 2 != 0 {
		w.Write([]byte{128})
		n++
	}
	return
}

// EncodedLen returns the length of WAV-encoded audio captcha.
func (a *Audio) EncodedLen() int {
	return len(waveHeader) + 4 + a.body.Len()
}

// mixSound mixes src into dst. Dst must have length equal to or greater than
// src length.
func mixSound(dst, src []byte) {
	for i, v := range src {
		av := int(v)
		bv := int(dst[i])
		if av < 128 && bv < 128 {
			dst[i] = byte(av * bv / 128)
		} else {
			dst[i] = byte(2*(av+bv) - av*bv/128 - 256)
		}
	}
}

func setSoundLevel(a []byte, level float64) {
	for i, v := range a {
		av := float64(v)
		switch {
		case av > 128:
			if av = (av-128)*level + 128; av < 128 {
				av = 128
			}
		case av < 128:
			if av = 128 - (128-av)*level; av > 128 {
				av = 128
			}
		default:
			continue
		}
		a[i] = byte(av)
	}
}

// changeSpeed returns new PCM bytes from the bytes with the speed and pitch
// changed to the given value that must be in range [0, x].
func changeSpeed(a []byte, speed float64) []byte {
	b := make([]byte, int(math.Floor(float64(len(a))*speed)))
	var p float64
	for _, v := range a {
		for i := int(p); i < int(p+speed); i++ {
			b[i] = v
		}
		p += speed
	}
	return b
}

func randomSpeed(a []byte) []byte {
	pitch := rndf(0.9, 1.2)
	return changeSpeed(a, pitch)
}

func makeSilence(length int) []byte {
	b := make([]byte, length)
	for i := range b {
		b[i] = 128
	}
	return b
}

func makeWhiteNoise(length int, level uint8) []byte {
	noise := randomBytes(length)
	adj := 128 - level/2
	for i, v := range noise {
		v %= level
		v += adj
		noise[i] = v
	}
	return noise
}

func reversedSound(a []byte) []byte {
	n := len(a)
	b := make([]byte, n)
	for i, v := range a {
		b[n-1-i] = v
	}
	return b
}

func makeBackgroundSound(length int) []byte {
	b := makeWhiteNoise(length, 4)
	for i := 0; i < length/(sampleRate/10); i++ {
		snd := reverseDigitSounds[rand.Intn(10)]
		snd = changeSpeed(snd, rndf(0.8, 1.4))
		place := rand.Intn(len(b) - len(snd))
		setSoundLevel(snd, rndf(0.2, 0.3))
		mixSound(b[place:], snd)
	}
	return b
}

func randomizedDigitSound(n byte) []byte {
	s := randomSpeed(digitSounds[n])
	setSoundLevel(s, rndf(0.7, 1.3))
	return s
}
<|endoftext|>


<commit_before><commit_msg>BugFix allow multiple figure elements in Header<commit_after><|endoftext|>


<commit_before>package viber_bot

import (
	"github.com/strongo/bots-api-viber/viberinterface"
	"github.com/strongo/bots-framework/core"
)

type ViberSender struct {
	sender viberinterface.CallbackSender
}

var _ bots.WebhookSender = (*ViberSender)(nil)

func (ViberSender) IsBotUser() bool {
	return false
}

func (s ViberSender) GetID() interface{} {
	return s.sender.ID
}

func (s ViberSender) GetFirstName() string {
	return ""
}

func (s ViberSender) GetLastName() string {
	return ""
}

func (s ViberSender) GetUserName() string {
	return s.sender.Name
}

func (s ViberSender) GetAvatar() string {
	return s.sender.Avatar
}

func (_ ViberSender) Platform() string {
	return ViberPlatformID
}

func (_ ViberSender) GetLanguage() string {
	return "" // TODO: Check if we can return actual
}

func newViberSender(sender viberinterface.CallbackSender) ViberSender {
	return ViberSender{sender: sender}
}
<commit_msg>golint for Viber<commit_after>package viber_bot

import (
	"github.com/strongo/bots-api-viber/viberinterface"
	"github.com/strongo/bots-framework/core"
)

// ViberSender sends messages to Viber
type ViberSender struct {
	sender viberinterface.CallbackSender
}

var _ bots.WebhookSender = (*ViberSender)(nil)

// IsBotUser returns true if message sent by a bot, always false for Viber
func (ViberSender) IsBotUser() bool {
	return false
}

// GetID returns ID of Viber user
func (s ViberSender) GetID() interface{} {
	return s.sender.ID
}

// GetFirstName returns first name of Viber user
func (s ViberSender) GetFirstName() string {
	return ""
}

// GetLastName returns last name of Viber user
func (s ViberSender) GetLastName() string {
	return ""
}

// GetUserName returns nickname of Viber user
func (s ViberSender) GetUserName() string {
	return s.sender.Name
}

// GetAvatar returns avatar URL
func (s ViberSender) GetAvatar() string {
	return s.sender.Avatar
}

// Platform returns 'viber'
func (_ ViberSender) Platform() string {
	return ViberPlatformID
}

// GetLanguage is not implemented yet
func (_ ViberSender) GetLanguage() string {
	return "" // TODO: Check if we can return actual
}

func newViberSender(sender viberinterface.CallbackSender) ViberSender {
	return ViberSender{sender: sender}
}
<|endoftext|>


<commit_before>// +build linux darwin

package fingerprint

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os/exec"
	"regexp"
	"strconv"
	"strings"

	"github.com/hashicorp/nomad/client/config"
	"github.com/hashicorp/nomad/nomad/structs"
)

// NetworkFingerprint is used to fingerprint the Network capabilities of a node
type NetworkFingerprint struct {
	logger *log.Logger
}

// NewNetworkFingerprinter returns a new NetworkFingerprinter with the given
// logger
func NewNetworkFingerprinter(logger *log.Logger) Fingerprint {
	f := &NetworkFingerprint{logger: logger}
	return f
}

func (f *NetworkFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
	// newNetwork is populated and addded to the Nodes resources
	newNetwork := &structs.NetworkResource{}
	var ip string

	interfaces, err := f.findInterfaces(cfg.NetworkInterface)
	if err != nil {
		f.logger.Println(fmt.Sprintf("[DEBUG] Error while detecting network interface during fingerprinting: %s", err.Error()))
		return false, err
	}

	if len(interfaces) == 0 {
		f.logger.Println("[DEBUG] No network interfaces were detected")
		return false, errors.New("Unable to find any interface")
	}

	// Use the first interface that we have detected.
	intf := interfaces[0]
	if ip, err = f.ipAddress(intf); err != nil {
		f.logger.Println("[DEBUG] Unable to find IP address of interface ", intf.Name)
		return false, err
	}

	newNetwork.Device = intf.Name
	node.Attributes["network.ip-address"] = ip
	newNetwork.IP = ip
	newNetwork.CIDR = newNetwork.IP + "/32"

	f.logger.Println("[DEBUG] Detected interface ", intf.Name, " with IP ", ip, " during fingerprinting")

	if throughput := f.linkSpeed(intf.Name); throughput > 0 {
		newNetwork.MBits = throughput
	} else {
		f.logger.Printf("[DEBUG] fingerprint.network: Unable to read link speed; setting to default %v", cfg.NetworkSpeed)
		newNetwork.MBits = cfg.NetworkSpeed
	}

	if node.Resources == nil {
		node.Resources = &structs.Resources{}
	}

	node.Resources.Networks = append(node.Resources.Networks, newNetwork)

	// return true, because we have a network connection
	return true, nil
}

// linkSpeed returns link speed in Mb/s, or 0 when unable to determine it.
func (f *NetworkFingerprint) linkSpeed(device string) int {
	// Use LookPath to find the ethtool in the systems $PATH
	// If it's not found or otherwise errors, LookPath returns and empty string
	// and an error we can ignore for our purposes
	ethtoolPath, _ := exec.LookPath("ethtool")
	if ethtoolPath != "" {
		if speed := f.linkSpeedEthtool(ethtoolPath, device); speed > 0 {
			return speed
		}
	}

	// Fall back on checking a system file for link speed.
	return f.linkSpeedSys(device)
}

// linkSpeedSys parses link speed in Mb/s from /sys.
func (f *NetworkFingerprint) linkSpeedSys(device string) int {
	path := fmt.Sprintf("/sys/class/net/%s/speed", device)

	// Read contents of the device/speed file
	content, err := ioutil.ReadFile(path)
	if err != nil {
		f.logger.Printf("[WARN] fingerprint.network: Unable to read link speed from %s", path)
		return 0
	}

	lines := strings.Split(string(content), "\n")
	mbs, err := strconv.Atoi(lines[0])
	if err != nil || mbs <= 0 {
		f.logger.Printf("[WARN] fingerprint.network: Unable to parse link speed from %s", path)
		return 0
	}

	return mbs
}

// linkSpeedEthtool determines link speed in Mb/s with 'ethtool'.
func (f *NetworkFingerprint) linkSpeedEthtool(path, device string) int {
	outBytes, err := exec.Command(path, device).Output()
	if err != nil {
		f.logger.Printf("[WARN] fingerprint.network: Error calling ethtool (%s %s): %v", path, device, err)
		return 0
	}

	output := strings.TrimSpace(string(outBytes))
	re := regexp.MustCompile("Speed: [0-9]+[a-zA-Z]+/s")
	m := re.FindString(output)
	if m == "" {
		// no matches found, output may be in a different format
		f.logger.Printf("[WARN] fingerprint.network: Unable to parse Speed in output of '%s %s'", path, device)
		return 0
	}

	// Split and trim the Mb/s unit from the string output
	args := strings.Split(m, ": ")
	raw := strings.TrimSuffix(args[1], "Mb/s")

	// convert to Mb/s
	mbs, err := strconv.Atoi(raw)
	if err != nil || mbs <= 0 {
		f.logger.Printf("[WARN] fingerprint.network: Unable to parse Mb/s in output of '%s %s'", path, device)
		return 0
	}

	return mbs
}

func (f *NetworkFingerprint) ipAddress(intf *net.Interface) (string, error) {
	var (
		addrs []net.Addr
		err   error
	)
	if addrs, err = intf.Addrs(); err != nil {
		return "", err
	}

	if len(addrs) == 0 {
		return "", errors.New(fmt.Sprintf("Interface %s has no IP address", intf.Name))
	}
	if ip, _, err := net.ParseCIDR(addrs[0].String()); err == nil {
		return ip.String(), nil
	}
	return "", errors.New(fmt.Sprintf("Couldn't parse IP address for interface %s with addr %s", intf.Name, addrs[0].String()))
}

func (f *NetworkFingerprint) isDeviceEnabled(intf *net.Interface) bool {
	return intf.Flags&net.FlagUp != 0
}

func (f *NetworkFingerprint) deviceHasIpAddress(intf *net.Interface) bool {
	if addrs, err := intf.Addrs(); err == nil {
		return len(addrs) > 0
	}
	return false
}

func (n *NetworkFingerprint) isDeviceLoopBackOrPointToPoint(intf *net.Interface) bool {
	return intf.Flags&(net.FlagLoopback|net.FlagPointToPoint) == 0
}

func (f *NetworkFingerprint) findInterfaces(deviceName string) ([]*net.Interface, error) {
	var (
		interfaces []*net.Interface
		err        error
	)
	if deviceName != "" {
		if intf, err := net.InterfaceByName(deviceName); err == nil {
			interfaces = append(interfaces, intf)
		}
		return interfaces, err
	}

	var intfs []net.Interface

	if intfs, err = net.Interfaces(); err != nil {
		return nil, err
	}

	for _, intf := range intfs {
		if f.isDeviceEnabled(&intf) && f.isDeviceLoopBackOrPointToPoint(&intf) && f.deviceHasIpAddress(&intf) {
			interfaces = append(interfaces, &intf)
		}
	}

	return interfaces, nil
}
<commit_msg>Selecting the ipv4 address if there are ipv4 and ipv6 addresses configured for an interface<commit_after>// +build linux darwin

package fingerprint

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os/exec"
	"regexp"
	"strconv"
	"strings"

	"github.com/hashicorp/nomad/client/config"
	"github.com/hashicorp/nomad/nomad/structs"
)

// NetworkFingerprint is used to fingerprint the Network capabilities of a node
type NetworkFingerprint struct {
	logger *log.Logger
}

// NewNetworkFingerprinter returns a new NetworkFingerprinter with the given
// logger
func NewNetworkFingerprinter(logger *log.Logger) Fingerprint {
	f := &NetworkFingerprint{logger: logger}
	return f
}

func (f *NetworkFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
	// newNetwork is populated and addded to the Nodes resources
	newNetwork := &structs.NetworkResource{}
	var ip string

	interfaces, err := f.findInterfaces(cfg.NetworkInterface)
	if err != nil {
		f.logger.Println(fmt.Sprintf("[DEBUG] Error while detecting network interface during fingerprinting: %s", err.Error()))
		return false, err
	}

	if len(interfaces) == 0 {
		f.logger.Println("[DEBUG] No network interfaces were detected")
		return false, errors.New("Unable to find any interface")
	}

	// Use the first interface that we have detected.
	intf := interfaces[0]
	if ip, err = f.ipAddress(intf); err != nil {
		f.logger.Println("[DEBUG] Unable to find IP address of interface ", intf.Name)
		return false, err
	}

	newNetwork.Device = intf.Name
	node.Attributes["network.ip-address"] = ip
	newNetwork.IP = ip
	newNetwork.CIDR = newNetwork.IP + "/32"

	f.logger.Println("[DEBUG] Detected interface ", intf.Name, " with IP ", ip, " during fingerprinting")

	if throughput := f.linkSpeed(intf.Name); throughput > 0 {
		newNetwork.MBits = throughput
	} else {
		f.logger.Printf("[DEBUG] fingerprint.network: Unable to read link speed; setting to default %v", cfg.NetworkSpeed)
		newNetwork.MBits = cfg.NetworkSpeed
	}

	if node.Resources == nil {
		node.Resources = &structs.Resources{}
	}

	node.Resources.Networks = append(node.Resources.Networks, newNetwork)

	// return true, because we have a network connection
	return true, nil
}

// linkSpeed returns link speed in Mb/s, or 0 when unable to determine it.
func (f *NetworkFingerprint) linkSpeed(device string) int {
	// Use LookPath to find the ethtool in the systems $PATH
	// If it's not found or otherwise errors, LookPath returns and empty string
	// and an error we can ignore for our purposes
	ethtoolPath, _ := exec.LookPath("ethtool")
	if ethtoolPath != "" {
		if speed := f.linkSpeedEthtool(ethtoolPath, device); speed > 0 {
			return speed
		}
	}

	// Fall back on checking a system file for link speed.
	return f.linkSpeedSys(device)
}

// linkSpeedSys parses link speed in Mb/s from /sys.
func (f *NetworkFingerprint) linkSpeedSys(device string) int {
	path := fmt.Sprintf("/sys/class/net/%s/speed", device)

	// Read contents of the device/speed file
	content, err := ioutil.ReadFile(path)
	if err != nil {
		f.logger.Printf("[WARN] fingerprint.network: Unable to read link speed from %s", path)
		return 0
	}

	lines := strings.Split(string(content), "\n")
	mbs, err := strconv.Atoi(lines[0])
	if err != nil || mbs <= 0 {
		f.logger.Printf("[WARN] fingerprint.network: Unable to parse link speed from %s", path)
		return 0
	}

	return mbs
}

// linkSpeedEthtool determines link speed in Mb/s with 'ethtool'.
func (f *NetworkFingerprint) linkSpeedEthtool(path, device string) int {
	outBytes, err := exec.Command(path, device).Output()
	if err != nil {
		f.logger.Printf("[WARN] fingerprint.network: Error calling ethtool (%s %s): %v", path, device, err)
		return 0
	}

	output := strings.TrimSpace(string(outBytes))
	re := regexp.MustCompile("Speed: [0-9]+[a-zA-Z]+/s")
	m := re.FindString(output)
	if m == "" {
		// no matches found, output may be in a different format
		f.logger.Printf("[WARN] fingerprint.network: Unable to parse Speed in output of '%s %s'", path, device)
		return 0
	}

	// Split and trim the Mb/s unit from the string output
	args := strings.Split(m, ": ")
	raw := strings.TrimSuffix(args[1], "Mb/s")

	// convert to Mb/s
	mbs, err := strconv.Atoi(raw)
	if err != nil || mbs <= 0 {
		f.logger.Printf("[WARN] fingerprint.network: Unable to parse Mb/s in output of '%s %s'", path, device)
		return 0
	}

	return mbs
}

func (f *NetworkFingerprint) ipAddress(intf *net.Interface) (string, error) {
	var (
		addrs []net.Addr
		err   error
	)
	if addrs, err = intf.Addrs(); err != nil {
		return "", err
	}

	if len(addrs) == 0 {
		return "", errors.New(fmt.Sprintf("Interface %s has no IP address", intf.Name))
	}
	var ipV4 net.IP
	for _, addr := range addrs {
		var ip net.IP
		switch v := (addr).(type) {
		case *net.IPNet:
			ip = v.IP
		case *net.IPAddr:
			ip = v.IP
		}
		if ip.To4() != nil {
			ipV4 = ip
			break
		}
	}

	if ipV4 == nil {
		return "", errors.New(fmt.Sprintf("Couldn't parse IP address for interface %s with addr %s", intf.Name))
	}
	return ipV4.String(), nil

}

func (f *NetworkFingerprint) isDeviceEnabled(intf *net.Interface) bool {
	return intf.Flags&net.FlagUp != 0
}

func (f *NetworkFingerprint) deviceHasIpAddress(intf *net.Interface) bool {
	if addrs, err := intf.Addrs(); err == nil {
		return len(addrs) > 0
	}
	return false
}

func (n *NetworkFingerprint) isDeviceLoopBackOrPointToPoint(intf *net.Interface) bool {
	return intf.Flags&(net.FlagLoopback|net.FlagPointToPoint) == 0
}

func (f *NetworkFingerprint) findInterfaces(deviceName string) ([]*net.Interface, error) {
	var (
		interfaces []*net.Interface
		err        error
	)
	if deviceName != "" {
		if intf, err := net.InterfaceByName(deviceName); err == nil {
			interfaces = append(interfaces, intf)
		}
		return interfaces, err
	}

	var intfs []net.Interface

	if intfs, err = net.Interfaces(); err != nil {
		return nil, err
	}

	for _, intf := range intfs {
		if f.isDeviceEnabled(&intf) && f.isDeviceLoopBackOrPointToPoint(&intf) && f.deviceHasIpAddress(&intf) {
			interfaces = append(interfaces, &intf)
		}
	}

	return interfaces, nil
}
<|endoftext|>


<commit_before>package badge

import (
	"bytes"
	"html/template"
	"io"
	"sync"

	"github.com/golang/freetype/truetype"
	"github.com/narqo/go-badge/fonts"
	"golang.org/x/image/font"
)

type badge struct {
	Subject string
	Status  string
	Color   Color
	Bounds  bounds
}

type bounds struct {
	// SubjectDx is the width of subject string of the badge.
	SubjectDx float64
	SubjectX  float64
	// StatusDx is the width of status string of the badge.
	StatusDx float64
	StatusX  float64
}

func (b bounds) Dx() float64 {
	return b.SubjectDx + b.StatusDx
}

type badgeDrawer struct {
	fd    *font.Drawer
	tmpl  *template.Template
	mutex *sync.Mutex
}

func (d *badgeDrawer) Render(subject, status string, color Color, w io.Writer) error {
	d.mutex.Lock()
	subjectDx := d.measureString(subject)
	statusDx := d.measureString(status)
	d.mutex.Unlock()

	bdg := badge{
		Subject: subject,
		Status:  status,
		Color:   color,
		Bounds: bounds{
			SubjectDx: subjectDx,
			SubjectX:  subjectDx/2.0 + 1,
			StatusDx:  statusDx,
			StatusX:   subjectDx + statusDx/2.0 - 1,
		},
	}
	return d.tmpl.Execute(w, bdg)
}

func (d *badgeDrawer) RenderBytes(subject, status string, color Color) ([]byte, error) {
	buf := &bytes.Buffer{}
	err := d.Render(subject, status, color, buf)
	return buf.Bytes(), err
}

// shield.io uses Verdana.ttf to measure text width with an extra 10px.
// As we use Vera.ttf, we have to tune this value a little.
const extraDx = 13

func (d *badgeDrawer) measureString(s string) float64 {
	sm := d.fd.MeasureString(s)
	// this 64 is weird but it's the way I've found how to convert fixed.Int26_6 to float64
	return float64(sm)/64 + extraDx
}

// Render renders a badge of the given color, with given subject and status to w.
func Render(subject, status string, color Color, w io.Writer) error {
	return drawer.Render(subject, status, color, w)
}

// RenderBytes renders a badge of the given color, with given subject and status to bytes.
func RenderBytes(subject, status string, color Color) ([]byte, error) {
	return drawer.RenderBytes(subject, status, color)
}

const (
	dpi      = 72
	fontsize = 11
)

var drawer *badgeDrawer

func init() {
	drawer = &badgeDrawer{
		fd:    mustNewFontDrawer(fontsize, dpi),
		tmpl:  template.Must(template.New("flat-template").Parse(flatTemplate)),
		mutex: &sync.Mutex{},
	}
}

func mustNewFontDrawer(size, dpi float64) *font.Drawer {
	ttf, err := truetype.Parse(fonts.VeraSans)
	if err != nil {
		panic(err)
	}
	return &font.Drawer{
		Face: truetype.NewFace(ttf, &truetype.Options{
			Size:    size,
			DPI:     dpi,
			Hinting: font.HintingFull,
		}),
	}
}
<commit_msg>Add a better way to convert Int26_6 to float64<commit_after>package badge

import (
	"bytes"
	"html/template"
	"io"
	"sync"

	"github.com/golang/freetype/truetype"
	"github.com/narqo/go-badge/fonts"
	"golang.org/x/image/font"
)

type badge struct {
	Subject string
	Status  string
	Color   Color
	Bounds  bounds
}

type bounds struct {
	// SubjectDx is the width of subject string of the badge.
	SubjectDx float64
	SubjectX  float64
	// StatusDx is the width of status string of the badge.
	StatusDx float64
	StatusX  float64
}

func (b bounds) Dx() float64 {
	return b.SubjectDx + b.StatusDx
}

type badgeDrawer struct {
	fd    *font.Drawer
	tmpl  *template.Template
	mutex *sync.Mutex
}

func (d *badgeDrawer) Render(subject, status string, color Color, w io.Writer) error {
	d.mutex.Lock()
	subjectDx := d.measureString(subject)
	statusDx := d.measureString(status)
	d.mutex.Unlock()

	bdg := badge{
		Subject: subject,
		Status:  status,
		Color:   color,
		Bounds: bounds{
			SubjectDx: subjectDx,
			SubjectX:  subjectDx/2.0 + 1,
			StatusDx:  statusDx,
			StatusX:   subjectDx + statusDx/2.0 - 1,
		},
	}
	return d.tmpl.Execute(w, bdg)
}

func (d *badgeDrawer) RenderBytes(subject, status string, color Color) ([]byte, error) {
	buf := &bytes.Buffer{}
	err := d.Render(subject, status, color, buf)
	return buf.Bytes(), err
}

// shield.io uses Verdana.ttf to measure text width with an extra 10px.
// As we use Vera.ttf, we have to tune this value a little.
const extraDx = 13

func (d *badgeDrawer) measureString(s string) float64 {
	return float64(d.fd.MeasureString(s)>>6) + extraDx
}

// Render renders a badge of the given color, with given subject and status to w.
func Render(subject, status string, color Color, w io.Writer) error {
	return drawer.Render(subject, status, color, w)
}

// RenderBytes renders a badge of the given color, with given subject and status to bytes.
func RenderBytes(subject, status string, color Color) ([]byte, error) {
	return drawer.RenderBytes(subject, status, color)
}

const (
	dpi      = 72
	fontsize = 11
)

var drawer *badgeDrawer

func init() {
	drawer = &badgeDrawer{
		fd:    mustNewFontDrawer(fontsize, dpi),
		tmpl:  template.Must(template.New("flat-template").Parse(flatTemplate)),
		mutex: &sync.Mutex{},
	}
}

func mustNewFontDrawer(size, dpi float64) *font.Drawer {
	ttf, err := truetype.Parse(fonts.VeraSans)
	if err != nil {
		panic(err)
	}
	return &font.Drawer{
		Face: truetype.NewFace(ttf, &truetype.Options{
			Size:    size,
			DPI:     dpi,
			Hinting: font.HintingFull,
		}),
	}
}
<|endoftext|>


<commit_before>package jsval

import (
	"errors"
	"reflect"

	"github.com/lestrrat/go-pdebug"
)

func Array() *ArrayConstraint {
	return &ArrayConstraint{
		additionalItems: EmptyConstraint,
		minItems: -1,
	}
}

func (c *ArrayConstraint) Validate(v interface{}) (err error) {
	if pdebug.Enabled {
		g := pdebug.IPrintf("START ArrayConstraint.Validate")
		defer func() {
			if err == nil {
				g.IRelease("END ArrayConstraint.Validate (PASS)")
			} else {
				g.IRelease("END ArrayConstraint.Validate (FAIL): %s", err)
			}
		}()
	}

	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Slice:
	default:
		return errors.New("value must be a slice")
	}

	l := rv.Len()
	if celem := c.items; celem != nil {
		if pdebug.Enabled {
			pdebug.Printf("Checking if all items match a spec")
		}
		// if this is set, then all items must fulfill this.
		// additional items are ignored
		for i := 0; i < l; i++ {
			if err := celem.Validate(rv.Index(i).Interface()); err != nil {
				return err
			}
		}
	} else {
		// otherwise, check the positional specs, and apply the
		// additionalItems constraint
		lv := rv.Len()
		for i, cpos := range c.positionalItems {
			if lv <= i {
				break
			}
			if pdebug.Enabled {
				pdebug.Printf("Checking positional item at '%d'", i)
			}
			ev := rv.Index(i)
			// We don't do defaults and stuff here, because it's virtually
			// impossible to tell if this is "uninitialized"
			if err := cpos.Validate(ev.Interface()); err != nil {
				return err
			}
		}

		lp := len(c.positionalItems)
		if lp > 0 && l > lp { // we got more than positional schemas
			cadd := c.additionalItems
			if cadd == nil { // you can't have additionalItems!
				return errors.New("additional elements found in array")
			}
			for i := lp - 1; i < l; i++ {
				if err := cadd.Validate(rv.Index(i).Interface()); err != nil {
					return err
				}
			}
		}
	}
	return nil
}

func (c *ArrayConstraint) AdditionalItems(ac Constraint) *ArrayConstraint {
	c.additionalItems = ac
	return c
}

func (c *ArrayConstraint) Items(ac Constraint) *ArrayConstraint {
	c.items = ac
	return c
}

func (c *ArrayConstraint) MinItems(i int) *ArrayConstraint {
	c.minItems = i
	return c
}

func (c *ArrayConstraint) MaxItems(i int) *ArrayConstraint {
	c.maxItems = i
	return c
}

func (c *ArrayConstraint) PositionalItems(ac []Constraint) *ArrayConstraint {
	c.positionalItems = ac
	return c
}

func (c *ArrayConstraint) UniqueItems(b bool) *ArrayConstraint {
	c.uniqueItems = b
	return c
}<commit_msg>Actually check for min/maxItems<commit_after>package jsval

import (
	"errors"
	"reflect"

	"github.com/lestrrat/go-pdebug"
)

func Array() *ArrayConstraint {
	return &ArrayConstraint{
		additionalItems: EmptyConstraint,
		maxItems: -1,
		minItems: -1,
	}
}

func (c *ArrayConstraint) Validate(v interface{}) (err error) {
	if pdebug.Enabled {
		g := pdebug.IPrintf("START ArrayConstraint.Validate")
		defer func() {
			if err == nil {
				g.IRelease("END ArrayConstraint.Validate (PASS)")
			} else {
				g.IRelease("END ArrayConstraint.Validate (FAIL): %s", err)
			}
		}()
	}

	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Slice:
	default:
		return errors.New("value must be a slice")
	}

	l := rv.Len()

	if mi := c.minItems; mi > -1 && l < mi {
		return errors.New("fewer items than minItems")
	}

	if mi := c.maxItems; mi > -1 && l > mi {
		return errors.New("more items than maxItems")
	}

	if celem := c.items; celem != nil {
		if pdebug.Enabled {
			pdebug.Printf("Checking if all items match a spec")
		}
		// if this is set, then all items must fulfill this.
		// additional items are ignored
		for i := 0; i < l; i++ {
			if err := celem.Validate(rv.Index(i).Interface()); err != nil {
				return err
			}
		}
	} else {
		// otherwise, check the positional specs, and apply the
		// additionalItems constraint
		lv := rv.Len()
		for i, cpos := range c.positionalItems {
			if lv <= i {
				break
			}
			if pdebug.Enabled {
				pdebug.Printf("Checking positional item at '%d'", i)
			}
			ev := rv.Index(i)
			// We don't do defaults and stuff here, because it's virtually
			// impossible to tell if this is "uninitialized"
			if err := cpos.Validate(ev.Interface()); err != nil {
				return err
			}
		}

		lp := len(c.positionalItems)
		if lp > 0 && l > lp { // we got more than positional schemas
			cadd := c.additionalItems
			if cadd == nil { // you can't have additionalItems!
				return errors.New("additional elements found in array")
			}
			for i := lp - 1; i < l; i++ {
				if err := cadd.Validate(rv.Index(i).Interface()); err != nil {
					return err
				}
			}
		}
	}
	return nil
}

func (c *ArrayConstraint) AdditionalItems(ac Constraint) *ArrayConstraint {
	c.additionalItems = ac
	return c
}

func (c *ArrayConstraint) Items(ac Constraint) *ArrayConstraint {
	c.items = ac
	return c
}

func (c *ArrayConstraint) MinItems(i int) *ArrayConstraint {
	c.minItems = i
	return c
}

func (c *ArrayConstraint) MaxItems(i int) *ArrayConstraint {
	c.maxItems = i
	return c
}

func (c *ArrayConstraint) PositionalItems(ac []Constraint) *ArrayConstraint {
	c.positionalItems = ac
	return c
}

func (c *ArrayConstraint) UniqueItems(b bool) *ArrayConstraint {
	c.uniqueItems = b
	return c
}<|endoftext|>


<commit_before>package main

import "math/big"

// Returns the smaller of x and y. No copies are made, so the returned
// pointer is either x or y.
func Min(x, y *big.Int) *big.Int {
	if x.Cmp(y) < 0 {
		return x
	}
	return y
}

// Returns the larger of x and y. No copies are made, so the returned
// pointer is either x or y.
func Max(x, y *big.Int) *big.Int {
	if x.Cmp(y) > 0 {
		return x
	}
	return y
}

// Returns the greatest number y such that y^k <= x. x must be
// non-negative and k must be positive.
func FloorRoot(x, k *big.Int) *big.Int {
	if x.Sign() < 0 {
		panic("negative radicand")
	}
	if k.Sign() <= 0 {
		panic("non-negative index")
	}
	if x.Sign() == 0 {
		return &big.Int{}
	}
	one := big.NewInt(1)
	var kMinusOne big.Int
	kMinusOne.Sub(k, one)

	// Calculate p = ceil((floor(lg(x)) + 1)/k).
	var p, r big.Int
	p.DivMod(big.NewInt(int64(x.BitLen())), k, &r)
	if r.Sign() > 0 {
		p.Add(&p, one)
	}

	y := &big.Int{}
	y.Exp(big.NewInt(2), &p, nil)
	for y.Cmp(one) > 0 {
		// Calculate z = floor(((k-1)y + floor(x/y^{k-1}))/k).
		var z1 big.Int
		z1.Mul(&kMinusOne, y)

		var z2 big.Int
		var yPowKMinusOne big.Int
		yPowKMinusOne.Exp(y, &kMinusOne, nil)
		z2.Div(x, &yPowKMinusOne)

		var z big.Int
		z.Add(&z1, &z2)
		z.Div(&z, k)

		if z.Cmp(y) >= 0 {
			return y
		}
		y = &z
	}
	return one
}

// Assuming p is prime, calculates and returns Phi(p^k) quickly.
func CalculateEulerPhiPrimePower(p, k *big.Int) *big.Int {
	var pMinusOne, kMinusOne big.Int
	pMinusOne.Sub(p, big.NewInt(1))
	kMinusOne.Sub(k, big.NewInt(1))
	var phi big.Int
	phi.Exp(p, &kMinusOne, nil)
	phi.Mul(&phi, &pMinusOne)
	return &phi
}

// A FactorFunction takes a prime and its multiplicity and returns
// whether or not to continue trying to find more factors.
type FactorFunction func(p, m *big.Int) bool

// Does trial division to find factors of n and passes them to the
// given FactorFunction until it indicates otherwise.
func TrialDivide(n *big.Int, factorFn FactorFunction) {
	one := big.NewInt(1)
	two := big.NewInt(2)
	three := big.NewInt(3)
	four := big.NewInt(4)
	five := big.NewInt(5)
	six := big.NewInt(6)
	seven := big.NewInt(7)
	eleven := big.NewInt(11)

	if n.Sign() < 0 {
		panic("negative n")
	}
	if n.Sign() == 0 {
		return
	}

	t := &big.Int{}
	t.Set(n)
	// Factors out d from t as much as possible and calls factorFn
	// if d divides t.
	factorOut := func(d *big.Int) bool {
		var m big.Int
		for {
			var q, r big.Int
			q.QuoRem(t, d, &r)
			if r.Sign() != 0 {
				break
			}
			t = &q
			m.Add(&m, one)
		}
		if m.Sign() != 0 {
			if !factorFn(d, &m) {
				return false
			}
		}
		return true
	}

	sqrtN := FloorRoot(n, two)

	// Try small primes first.
	if two.Cmp(t) <= 0 && two.Cmp(sqrtN) <= 0 && !factorOut(two) {
		return
	}

	if three.Cmp(t) <= 0 && three.Cmp(sqrtN) <= 0 && !factorOut(three) {
		return
	}

	if five.Cmp(t) <= 0 && five.Cmp(sqrtN) <= 0 && !factorOut(five) {
		return
	}

	if seven.Cmp(t) <= 0 && seven.Cmp(sqrtN) <= 0 && !factorOut(seven) {
		return
	}

	// Then run through a mod-30 wheel, which cuts the number of
	// odd numbers to test roughly in half.
	mod30Wheel := []*big.Int{four, two, four, two, four, six, two, six}
	for i, d := 1, eleven; d.Cmp(t) <= 0 && d.Cmp(sqrtN) <= 0; {
		if !factorOut(d) {
			return
		}
		d.Add(d, mod30Wheel[i])
		i = (i + 1) % len(mod30Wheel)
	}
	if t.Cmp(one) != 0 {
		factorFn(t, one)
	}
}

// Assuming that p is prime and a and p^k are coprime, returns the
// smallest power e of a such that a^e = 1 (mod p^k).
func CalculateMultiplicativeOrderPrimePower(a, p, k *big.Int) *big.Int {
	var n big.Int
	n.Exp(p, k, nil)
	t := CalculateEulerPhiPrimePower(p, k)

	o := big.NewInt(1)
	one := big.NewInt(1)
	processPrimeFactor := func(q, e *big.Int) bool {
		// Calculate x = a^(t/q^e) (mod n).
		var x big.Int
		x.Exp(q, e, nil)
		x.Div(t, &x)
		x.Exp(a, &x, &n)
		for x.Cmp(one) != 0 {
			o.Mul(o, q)
			x.Exp(&x, q, &n)
		}
		return true
	}

	if k.Cmp(one) > 0 {
		var kMinusOne big.Int
		kMinusOne.Sub(k, one)
		processPrimeFactor(p, &kMinusOne)
	}

	var pMinusOne big.Int
	pMinusOne.Sub(p, one)
	TrialDivide(&pMinusOne, processPrimeFactor)

	return o
}

// Assuming that a and n are coprime, returns the smallest power e of
// a such that a^e = 1 (mod n).
func CalculateMultiplicativeOrder(a, n *big.Int) *big.Int {
	o := big.NewInt(1)
	TrialDivide(n, func(q, e *big.Int) bool {
		oq := CalculateMultiplicativeOrderPrimePower(a, q, e)
		// Set o to lcm(o, oq).
		var gcd big.Int
		gcd.GCD(nil, nil, o, oq)
		o.Div(o, &gcd)
		o.Mul(o, oq)
		return true
	})
	return o
}

// Calculate Phi(n) by factorizing it.
func CalculateEulerPhi(n *big.Int) *big.Int {
	phi := big.NewInt(1)
	TrialDivide(n, func(q, e *big.Int) bool {
		phi.Mul(phi, CalculateEulerPhiPrimePower(q, e))
		return true
	})
	return phi
}
<commit_msg>Keep track of an upper bound in TrialDivide<commit_after>package main

import "math/big"

// Returns the smaller of x and y. No copies are made, so the returned
// pointer is either x or y.
func Min(x, y *big.Int) *big.Int {
	if x.Cmp(y) < 0 {
		return x
	}
	return y
}

// Returns the larger of x and y. No copies are made, so the returned
// pointer is either x or y.
func Max(x, y *big.Int) *big.Int {
	if x.Cmp(y) > 0 {
		return x
	}
	return y
}

// Returns the greatest number y such that y^k <= x. x must be
// non-negative and k must be positive.
func FloorRoot(x, k *big.Int) *big.Int {
	if x.Sign() < 0 {
		panic("negative radicand")
	}
	if k.Sign() <= 0 {
		panic("non-negative index")
	}
	if x.Sign() == 0 {
		return &big.Int{}
	}
	one := big.NewInt(1)
	var kMinusOne big.Int
	kMinusOne.Sub(k, one)

	// Calculate p = ceil((floor(lg(x)) + 1)/k).
	var p, r big.Int
	p.DivMod(big.NewInt(int64(x.BitLen())), k, &r)
	if r.Sign() > 0 {
		p.Add(&p, one)
	}

	y := &big.Int{}
	y.Exp(big.NewInt(2), &p, nil)
	for y.Cmp(one) > 0 {
		// Calculate z = floor(((k-1)y + floor(x/y^{k-1}))/k).
		var z1 big.Int
		z1.Mul(&kMinusOne, y)

		var z2 big.Int
		var yPowKMinusOne big.Int
		yPowKMinusOne.Exp(y, &kMinusOne, nil)
		z2.Div(x, &yPowKMinusOne)

		var z big.Int
		z.Add(&z1, &z2)
		z.Div(&z, k)

		if z.Cmp(y) >= 0 {
			return y
		}
		y = &z
	}
	return one
}

// Assuming p is prime, calculates and returns Phi(p^k) quickly.
func CalculateEulerPhiPrimePower(p, k *big.Int) *big.Int {
	var pMinusOne, kMinusOne big.Int
	pMinusOne.Sub(p, big.NewInt(1))
	kMinusOne.Sub(k, big.NewInt(1))
	var phi big.Int
	phi.Exp(p, &kMinusOne, nil)
	phi.Mul(&phi, &pMinusOne)
	return &phi
}

// A FactorFunction takes a prime and its multiplicity and returns
// whether or not to continue trying to find more factors.
type FactorFunction func(p, m *big.Int) bool

// Does trial division to find factors of n and passes them to the
// given FactorFunction until it indicates otherwise.
func TrialDivide(n *big.Int, factorFn FactorFunction) {
	one := big.NewInt(1)
	two := big.NewInt(2)
	three := big.NewInt(3)
	four := big.NewInt(4)
	five := big.NewInt(5)
	six := big.NewInt(6)
	seven := big.NewInt(7)
	eleven := big.NewInt(11)

	if n.Sign() < 0 {
		panic("negative n")
	}
	if n.Sign() == 0 {
		return
	}

	upperBound := FloorRoot(n, two)

	t := &big.Int{}
	t.Set(n)

	// Factors out d from t as much as possible and calls factorFn
	// if d divides t.
	factorOut := func(d *big.Int) bool {
		var m big.Int
		for {
			var q, r big.Int
			q.QuoRem(t, d, &r)
			if r.Sign() != 0 {
				break
			}
			t = &q
			upperBound = Min(upperBound, t)
			m.Add(&m, one)
		}
		if m.Sign() != 0 {
			if !factorFn(d, &m) {
				return false
			}
		}
		return true
	}

	// Try small primes first.
	if two.Cmp(upperBound) <= 0 && !factorOut(two) {
		return
	}

	if three.Cmp(upperBound) <= 0 && !factorOut(three) {
		return
	}

	if five.Cmp(upperBound) <= 0 && !factorOut(five) {
		return
	}

	if seven.Cmp(upperBound) <= 0 && !factorOut(seven) {
		return
	}

	// Then run through a mod-30 wheel, which cuts the number of
	// odd numbers to test roughly in half.
	mod30Wheel := []*big.Int{four, two, four, two, four, six, two, six}
	for i, d := 1, eleven; d.Cmp(upperBound) <= 0; {
		if !factorOut(d) {
			return
		}
		d.Add(d, mod30Wheel[i])
		i = (i + 1) % len(mod30Wheel)
	}
	if t.Cmp(one) != 0 {
		factorFn(t, one)
	}
}

// Assuming that p is prime and a and p^k are coprime, returns the
// smallest power e of a such that a^e = 1 (mod p^k).
func CalculateMultiplicativeOrderPrimePower(a, p, k *big.Int) *big.Int {
	var n big.Int
	n.Exp(p, k, nil)
	t := CalculateEulerPhiPrimePower(p, k)

	o := big.NewInt(1)
	one := big.NewInt(1)
	processPrimeFactor := func(q, e *big.Int) bool {
		// Calculate x = a^(t/q^e) (mod n).
		var x big.Int
		x.Exp(q, e, nil)
		x.Div(t, &x)
		x.Exp(a, &x, &n)
		for x.Cmp(one) != 0 {
			o.Mul(o, q)
			x.Exp(&x, q, &n)
		}
		return true
	}

	if k.Cmp(one) > 0 {
		var kMinusOne big.Int
		kMinusOne.Sub(k, one)
		processPrimeFactor(p, &kMinusOne)
	}

	var pMinusOne big.Int
	pMinusOne.Sub(p, one)
	TrialDivide(&pMinusOne, processPrimeFactor)

	return o
}

// Assuming that a and n are coprime, returns the smallest power e of
// a such that a^e = 1 (mod n).
func CalculateMultiplicativeOrder(a, n *big.Int) *big.Int {
	o := big.NewInt(1)
	TrialDivide(n, func(q, e *big.Int) bool {
		oq := CalculateMultiplicativeOrderPrimePower(a, q, e)
		// Set o to lcm(o, oq).
		var gcd big.Int
		gcd.GCD(nil, nil, o, oq)
		o.Div(o, &gcd)
		o.Mul(o, oq)
		return true
	})
	return o
}

// Calculate Phi(n) by factorizing it.
func CalculateEulerPhi(n *big.Int) *big.Int {
	phi := big.NewInt(1)
	TrialDivide(n, func(q, e *big.Int) bool {
		phi.Mul(phi, CalculateEulerPhiPrimePower(q, e))
		return true
	})
	return phi
}
<|endoftext|>


<commit_before>package jet

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

var (
	markRx = regexp.MustCompile(`\$\d+`)
	mark   = "$0"
)

func substituteMapAndArrayMarks(query string, args ...interface{}) (string, []interface{}) {
	newArgs := make([]interface{}, 0, len(args)*2)
	newParts := []string{}

	for i, part := range regexpSplit(markRx, query, -1) {
		newParts = append(newParts, part)
		if i > len(args)-1 {
			break
		}
		arg := args[i]
		val := reflect.ValueOf(arg)
		switch val.Kind() {
		case reflect.Map:
			serializeMap(val, &newArgs, &newParts)
		case reflect.Slice:
			serializeSlice(val, &newArgs, &newParts)
		default:
			newParts = append(newParts, mark)
			newArgs = append(newArgs, arg)
		}
	}
	return sanitizeMarkEnumeration(strings.Join(newParts, "")), newArgs
}

func serializeSlice(v reflect.Value, newArgs *[]interface{}, newParts *[]string) {
	a := make([]string, 0, v.Len())
	for i := 0; i < v.Len(); i++ {
		val := v.Index(i)
		a = append(a, mark)
		*newArgs = append(*newArgs, val.Interface())
	}
	*newParts = append(*newParts, strings.Join(a, ", "))
}

func serializeMap(v reflect.Value, newArgs *[]interface{}, newParts *[]string) {
	a := make([]interface{}, 0, v.Len()*2)
	for _, keyVal := range v.MapKeys() {
		val := v.MapIndex(keyVal)
		a = append(a, keyVal.Interface(), val.Interface())
	}
	*newParts = append(*newParts, "hstore(ARRAY[ ")
	serializeSlice(reflect.ValueOf(a), newArgs, newParts)
	*newParts = append(*newParts, " ])")
}

func sanitizeMarkEnumeration(query string) string {
	parts := regexpSplit(markRx, query, -1)
	a := make([]string, 0, len(parts)*2)
	for i, v := range parts {
		a = append(a, v)
		if i < len(parts)-1 {
			a = append(a, fmt.Sprintf("$%d", i+1))
		}
	}
	return strings.Join(a, "")
}

func parseHstoreColumn(s string) map[string]interface{} {
	lasti := 0
	quoteOpen := false
	escaped := false
	a := make([]string, 0, len(s))
	for i, r := range s {
		switch r {
		case '\\':
			escaped = true
		case '"':
			if !escaped {
				quoteOpen = !quoteOpen
				if quoteOpen {
					lasti = i
				} else {
					a = append(a, s[lasti:i+1])
				}
			}
			escaped = false
		default:
			escaped = false
		}
	}

	if len(a)%2 == 1 {
		panic(fmt.Sprintf("invalid hstore map: %v", a))
	}

	// Convert to map
	m := make(map[string]interface{}, len(a)/2)
	lastKey := ""
	for i, v := range a {
		uq, _ := strconv.Unquote(v)
		if i%2 == 0 {
			lastKey = uq
		} else {
			m[lastKey] = uq
		}
	}

	return m
}

// TODO: replace when Go 1.1. is released
// This is the split source from http://tip.golang.org/src/pkg/regexp/regexp.go?s=33145:33194#L1067
func regexpSplit(re *regexp.Regexp, s string, n int) []string {
	if n == 0 {
		return nil
	}
	if len(s) == 0 {
		return []string{""}
	}

	matches := re.FindAllStringIndex(s, n)
	strings := make([]string, 0, len(matches))

	beg := 0
	end := 0
	for _, match := range matches {
		if n > 0 && len(strings) >= n-1 {
			break
		}
		end = match[0]
		if match[1] != 0 {
			strings = append(strings, s[beg:end])
		}
		beg = match[1]
	}

	if end != len(s) {
		strings = append(strings, s[beg:])
	}

	return strings
}
<commit_msg>don't serialize byte slices<commit_after>package jet

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

var (
	markRx = regexp.MustCompile(`\$\d+`)
	mark   = "$0"
)

func substituteMapAndArrayMarks(query string, args ...interface{}) (string, []interface{}) {
	newArgs := make([]interface{}, 0, len(args)*2)
	newParts := []string{}

	for i, part := range regexpSplit(markRx, query, -1) {
		newParts = append(newParts, part)
		if i > len(args)-1 {
			break
		}
		arg := args[i]
		val := reflect.ValueOf(arg)
		k := val.Kind()

		if k == reflect.Map {
			serializeMap(val, &newArgs, &newParts)
		} else if k == reflect.Slice && val.Type() != reflect.TypeOf([]byte{}) {
			serializeSlice(val, &newArgs, &newParts)
		} else {
			newParts = append(newParts, mark)
			newArgs = append(newArgs, arg)
		}
	}
	return sanitizeMarkEnumeration(strings.Join(newParts, "")), newArgs
}

func serializeSlice(v reflect.Value, newArgs *[]interface{}, newParts *[]string) {
	a := make([]string, 0, v.Len())
	for i := 0; i < v.Len(); i++ {
		val := v.Index(i)
		a = append(a, mark)
		*newArgs = append(*newArgs, val.Interface())
	}
	*newParts = append(*newParts, strings.Join(a, ", "))
}

func serializeMap(v reflect.Value, newArgs *[]interface{}, newParts *[]string) {
	a := make([]interface{}, 0, v.Len()*2)
	for _, keyVal := range v.MapKeys() {
		val := v.MapIndex(keyVal)
		a = append(a, keyVal.Interface(), val.Interface())
	}
	*newParts = append(*newParts, "hstore(ARRAY[ ")
	serializeSlice(reflect.ValueOf(a), newArgs, newParts)
	*newParts = append(*newParts, " ])")
}

func sanitizeMarkEnumeration(query string) string {
	parts := regexpSplit(markRx, query, -1)
	a := make([]string, 0, len(parts)*2)
	for i, v := range parts {
		a = append(a, v)
		if i < len(parts)-1 {
			a = append(a, fmt.Sprintf("$%d", i+1))
		}
	}
	return strings.Join(a, "")
}

func parseHstoreColumn(s string) map[string]interface{} {
	lasti := 0
	quoteOpen := false
	escaped := false
	a := make([]string, 0, len(s))
	for i, r := range s {
		switch r {
		case '\\':
			escaped = true
		case '"':
			if !escaped {
				quoteOpen = !quoteOpen
				if quoteOpen {
					lasti = i
				} else {
					a = append(a, s[lasti:i+1])
				}
			}
			escaped = false
		default:
			escaped = false
		}
	}

	if len(a)%2 == 1 {
		panic(fmt.Sprintf("invalid hstore map: %v", a))
	}

	// Convert to map
	m := make(map[string]interface{}, len(a)/2)
	lastKey := ""
	for i, v := range a {
		uq, _ := strconv.Unquote(v)
		if i%2 == 0 {
			lastKey = uq
		} else {
			m[lastKey] = uq
		}
	}

	return m
}

// TODO: replace when Go 1.1. is released
// This is the split source from http://tip.golang.org/src/pkg/regexp/regexp.go?s=33145:33194#L1067
func regexpSplit(re *regexp.Regexp, s string, n int) []string {
	if n == 0 {
		return nil
	}
	if len(s) == 0 {
		return []string{""}
	}

	matches := re.FindAllStringIndex(s, n)
	strings := make([]string, 0, len(matches))

	beg := 0
	end := 0
	for _, match := range matches {
		if n > 0 && len(strings) >= n-1 {
			break
		}
		end = match[0]
		if match[1] != 0 {
			strings = append(strings, s[beg:end])
		}
		beg = match[1]
	}

	if end != len(s) {
		strings = append(strings, s[beg:])
	}

	return strings
}
<|endoftext|>


<commit_before>package QesyGo

import (
	"math/rand"
	"strconv"
)

func Array_merge(arr ...[]string) []string {
	var retArr []string
	for _, n := range arr {
		for _, v := range n {
			retArr = append(retArr, v)
		}
	}
	return retArr
}

func Array_merge_int(arr ...[]int) []int {
	var retArr []int
	for _, n := range arr {
		for _, v := range n {
			retArr = append(retArr, v)
		}
	}
	return retArr
}

func InArray(Arr interface{}, str string) bool {
	strArr, ok := Arr.([]string)
	if ok {
		for _, v := range strArr {
			if v == str {
				return true
			}
		}
		return false
	}
	mapArr, ok := Arr.(map[string]string)
	if ok {
		for _, v := range mapArr {
			if v == str {
				return true
			}
		}
		return false
	}
	intArr, ok := Arr.([]int)
	if ok {
		for _, v := range intArr {
			if strconv.Itoa(v) == str {
				return true
			}
		}
		return false
	}
	return false

}

func Array_Rand(num int) []int {
	return rand.Perm(num)
}

func Array_Diff(Arr1 []int, Arr2 []int) []int {
	BigArr, SmallArr := Arr1, Arr2
	if len(Arr2) > len(Arr1) {
		BigArr = Arr2
		SmallArr = Arr1
	}
	TempArr := []int{}
	for _, v := range BigArr {
		if !InArray(SmallArr, strconv.Itoa(v)) {
			TempArr = append(TempArr, v)
		}
	}
	return TempArr
}

func Array_Mixed(Arr1 []int, Arr2 []int) []int {
	BigArr, SmallArr := Arr1, Arr2
	if len(Arr2) > len(Arr1) {
		BigArr = Arr2
		SmallArr = Arr1
	}
	TempArr := []int{}
	for _, v := range BigArr {
		if InArray(SmallArr, strconv.Itoa(v)) {
			TempArr = append(TempArr, v)
		}
	}
	return TempArr
}
<commit_msg>update array rand<commit_after>package QesyGo

import (
	"math/rand"
	"strconv"
)

func Array_merge(arr ...[]string) []string {
	var retArr []string
	for _, n := range arr {
		for _, v := range n {
			retArr = append(retArr, v)
		}
	}
	return retArr
}

func Array_merge_int(arr ...[]int) []int {
	var retArr []int
	for _, n := range arr {
		for _, v := range n {
			retArr = append(retArr, v)
		}
	}
	return retArr
}

func InArray(Arr interface{}, str string) bool {
	strArr, ok := Arr.([]string)
	if ok {
		for _, v := range strArr {
			if v == str {
				return true
			}
		}
		return false
	}
	mapArr, ok := Arr.(map[string]string)
	if ok {
		for _, v := range mapArr {
			if v == str {
				return true
			}
		}
		return false
	}
	intArr, ok := Arr.([]int)
	if ok {
		for _, v := range intArr {
			if strconv.Itoa(v) == str {
				return true
			}
		}
		return false
	}
	return false

}

func Array_Rand(num int) []int {
	rand.Seed(time.Now().UnixNano())
	return rand.Perm(num)
}

func Array_Diff(Arr1 []int, Arr2 []int) []int {
	BigArr, SmallArr := Arr1, Arr2
	if len(Arr2) > len(Arr1) {
		BigArr = Arr2
		SmallArr = Arr1
	}
	TempArr := []int{}
	for _, v := range BigArr {
		if !InArray(SmallArr, strconv.Itoa(v)) {
			TempArr = append(TempArr, v)
		}
	}
	return TempArr
}

func Array_Mixed(Arr1 []int, Arr2 []int) []int {
	BigArr, SmallArr := Arr1, Arr2
	if len(Arr2) > len(Arr1) {
		BigArr = Arr2
		SmallArr = Arr1
	}
	TempArr := []int{}
	for _, v := range BigArr {
		if InArray(SmallArr, strconv.Itoa(v)) {
			TempArr = append(TempArr, v)
		}
	}
	return TempArr
}
<|endoftext|>