<commit_before>// +build linux,seccomp

package native

import "github.com/opencontainers/runc/libcontainer/configs"

var defaultSeccompProfile = &configs.Seccomp{
	DefaultAction: configs.Allow,
	Syscalls: []*configs.Syscall{
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "acct",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "add_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Similar to clock_settime and settimeofday
			// Time/Date is not namespaced
			Name:   "adjtimex",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_adjtime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_settime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny cloning new namespaces
			Name:   "clone",
			Action: configs.Errno,
			Args: []*configs.Arg{
				{
					// flags from sched.h
					// CLONE_NEWUTS		0x04000000
					// CLONE_NEWIPC		0x08000000
					// CLONE_NEWUSER	0x10000000
					// CLONE_NEWPID		0x20000000
					// CLONE_NEWNET		0x40000000
					Index: 0,
					Value: uint64(0x04000000),
					Op:    configs.GreaterThanOrEqualTo,
				},
				{
					// flags from sched.h
					// CLONE_NEWNS		0x00020000
					Index: 0,
					Value: uint64(0x00020000),
					Op:    configs.EqualTo,
				},
			},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "create_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "delete_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "finit_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny retrieval of exported kernel and module symbols
			Name:   "get_kernel_syms",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "get_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "init_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "ioperm",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "iopl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Restrict process inspection capabilities
			// Already blocked by dropping CAP_PTRACE
			Name:   "kcmp",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Sister syscall of kexec_load that does the same thing,
			// slightly different arguments
			Name:   "kexec_file_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny loading a new kernel for later execution
			Name:   "kexec_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "keyctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "lookup_dcookie",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "mbind",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "migrate_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Old syscall only used in 16-bit code,
			// and a potential information leak
			Name:   "modify_ldt",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny mount
			Name:   "mount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "move_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny interaction with the kernel nfs daemon
			Name:   "nfsservctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Cause of an old container breakout,
			// might as well restrict it to be on the safe side
			Name:   "open_by_handle_at",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "perf_event_open",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent container from enabling BSD emulation.
			// Not inherently dangerous, but poorly tested,
			// potential for a lot of kernel vulns in this.
			Name:   "personality",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny pivot_root
			Name:   "pivot_root",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Restrict process inspection capabilities
			// Already blocked by dropping CAP_PTRACE
			Name:   "process_vm_readv",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Restrict process modification capabilities
			// Already blocked by dropping CAP_PTRACE
			Name:   "process_vm_writev",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Already blocked by dropping CAP_PTRACE
			Name:   "ptrace",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "query_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "quotactl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers reboot the host
			Name:   "reboot",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers restart a syscall.
			// Possible seccomp bypass, see: https://code.google.com/p/chromium/issues/detail?id=408827.
			Name:   "restart_syscall",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "request_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// meta, deny seccomp
			Name:   "seccomp",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "set_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// deny associating a thread with a namespace
			Name:   "setns",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "settimeofday",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "stime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapon",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapoff",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny read/write system parameters
			Name:   "_sysctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount2",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Same as clone
			Name:   "unshare",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Older syscall related to shared libraries, unused for a long time
			Name:   "uselib",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
	},
}
<commit_msg>Block bpf syscall from default seccomp profile<commit_after>// +build linux,seccomp

package native

import "github.com/opencontainers/runc/libcontainer/configs"

var defaultSeccompProfile = &configs.Seccomp{
	DefaultAction: configs.Allow,
	Syscalls: []*configs.Syscall{
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "acct",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "add_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Similar to clock_settime and settimeofday
			// Time/Date is not namespaced
			Name:   "adjtimex",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny loading potentially persistent bpf programs into kernel
			// already gated by CAP_SYS_ADMIN
			Name:   "bpf",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_adjtime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "clock_settime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny cloning new namespaces
			Name:   "clone",
			Action: configs.Errno,
			Args: []*configs.Arg{
				{
					// flags from sched.h
					// CLONE_NEWUTS		0x04000000
					// CLONE_NEWIPC		0x08000000
					// CLONE_NEWUSER	0x10000000
					// CLONE_NEWPID		0x20000000
					// CLONE_NEWNET		0x40000000
					Index: 0,
					Value: uint64(0x04000000),
					Op:    configs.GreaterThanOrEqualTo,
				},
				{
					// flags from sched.h
					// CLONE_NEWNS		0x00020000
					Index: 0,
					Value: uint64(0x00020000),
					Op:    configs.EqualTo,
				},
			},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "create_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "delete_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "finit_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny retrieval of exported kernel and module symbols
			Name:   "get_kernel_syms",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "get_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "init_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "ioperm",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from modifying kernel I/O privilege levels.
			// Already restricted as containers drop CAP_SYS_RAWIO by default.
			Name:   "iopl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Restrict process inspection capabilities
			// Already blocked by dropping CAP_PTRACE
			Name:   "kcmp",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Sister syscall of kexec_load that does the same thing,
			// slightly different arguments
			Name:   "kexec_file_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny loading a new kernel for later execution
			Name:   "kexec_load",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "keyctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "lookup_dcookie",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "mbind",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "migrate_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Old syscall only used in 16-bit code,
			// and a potential information leak
			Name:   "modify_ldt",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny mount
			Name:   "mount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "move_pages",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny interaction with the kernel nfs daemon
			Name:   "nfsservctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Cause of an old container breakout,
			// might as well restrict it to be on the safe side
			Name:   "open_by_handle_at",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Tracing/profiling syscalls,
			// which could leak a lot of information on the host
			Name:   "perf_event_open",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent container from enabling BSD emulation.
			// Not inherently dangerous, but poorly tested,
			// potential for a lot of kernel vulns in this.
			Name:   "personality",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny pivot_root
			Name:   "pivot_root",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Restrict process inspection capabilities
			// Already blocked by dropping CAP_PTRACE
			Name:   "process_vm_readv",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Restrict process modification capabilities
			// Already blocked by dropping CAP_PTRACE
			Name:   "process_vm_writev",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Already blocked by dropping CAP_PTRACE
			Name:   "ptrace",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny manipulation and functions on kernel modules.
			Name:   "query_module",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Quota and Accounting syscalls which could let containers
			// disable their own resource limits or process accounting
			Name:   "quotactl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers reboot the host
			Name:   "reboot",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Probably a bad idea to let containers restart a syscall.
			// Possible seccomp bypass, see: https://code.google.com/p/chromium/issues/detail?id=408827.
			Name:   "restart_syscall",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Prevent containers from using the kernel keyring,
			// which is not namespaced
			Name:   "request_key",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// meta, deny seccomp
			Name:   "seccomp",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Terrifying syscalls that modify kernel memory and NUMA settings.
			// They're gated by CAP_SYS_NICE,
			// which we do not retain by default in containers.
			Name:   "set_mempolicy",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// deny associating a thread with a namespace
			Name:   "setns",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "settimeofday",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Time/Date is not namespaced
			Name:   "stime",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapon",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny start/stop swapping to file/device
			Name:   "swapoff",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny read/write system parameters
			Name:   "_sysctl",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Deny umount
			Name:   "umount2",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Same as clone
			Name:   "unshare",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
		{
			// Older syscall related to shared libraries, unused for a long time
			Name:   "uselib",
			Action: configs.Errno,
			Args:   []*configs.Arg{},
		},
	},
}
<|endoftext|>


<commit_before>package s3

import (
	"bytes"
	"io"
	"log"

	"github.com/goamz/goamz/aws"
	"github.com/goamz/goamz/s3"
)

type S3Creds struct {
	AccessKey string
	SecretKey string
}

type S3MultipartUploadSession struct {
	creds         S3Creds
	s3Region      string
	s3Bucket      string
	chunkSizeInMB int
}

func CleanupChunks(s3AccessKey string, s3SecretKey string, s3Region string, s3Bucket string) {
	auth := aws.Auth{
		AccessKey: s3AccessKey,
		SecretKey: s3SecretKey}

	b := s3.New(auth, aws.Regions[s3Region]).Bucket(s3Bucket)

	multis, _, _ := b.ListMulti("", "")

	for _, m := range multis {
		log.Println("Removing part files for: ", m)
		m.Abort()
	}
}

func NewS3Creds(accessKey string, secretKey string) S3Creds {
	return S3Creds{AccessKey: accessKey, SecretKey: secretKey}
}

func NewS3MultipartUpload(s3AccessKey string,
	s3SecretKey string,
	s3Region string,
	s3Bucket string,
	chunkSizeInMB int) S3MultipartUploadSession {
	return S3MultipartUploadSession{s3Bucket: s3Bucket,
		s3Region:      s3Region,
		chunkSizeInMB: chunkSizeInMB,
		creds: S3Creds{
			AccessKey: s3AccessKey,
			SecretKey: s3SecretKey}}
}

func (s *S3MultipartUploadSession) awsAuth() aws.Auth {
	return aws.Auth{
		AccessKey: s.creds.AccessKey,
		SecretKey: s.creds.SecretKey}
}

func (s *S3MultipartUploadSession) getS3Bucket() *s3.Bucket {
	auth := s.awsAuth()
	return s3.New(auth, aws.Regions[s.s3Region]).Bucket(s.s3Bucket)
}

func (s *S3MultipartUploadSession) UploadMultiPart(reader io.Reader, s3Path string) error {

	bucket := s.getS3Bucket()
	multi, err := bucket.InitMulti(s3Path, "text/plain", s3.Private)

	if err != nil {
		return err
	}

	parts, err := s.uploadMultiPart(multi, reader)

	var errCleanup error = nil

	if err != nil {
		log.Printf("Multipart upload for %s failed, aborting: %v\n", s3Path, err)
		errCleanup = multi.Abort()
	} else {
		log.Printf("Multipart upload for %s successful, stitching the parts.\n", s3Path)
		errCleanup = multi.Complete(parts)
	}

	if errCleanup != nil {
		log.Println("Abort or complete for %s failed. You should cleanup the parts manually: %v\n", s3Path, errCleanup)
	}

	return err
}

func (s *S3MultipartUploadSession) uploadMultiPart(multi *s3.Multi, reader io.Reader) ([]s3.Part, error) {

	var parts []s3.Part
	var totalBytesUploaded = 0
	const retryCount = 3

	dataChan := make(chan []byte)
	readFailure := make(chan error)
	sendFailure := make(chan struct{})
	errors := make(chan error, 2)

	go func() {
		defer close(dataChan)
		defer close(readFailure)
		for {
			data, errRead := readSinglePart(reader, s.chunkSizeInMB)
			select {
			case dataChan <- data:
				if errRead != nil {
					if errRead != io.EOF {
						readFailure <- errRead
						errors <- errRead
					}
					return
				}
			case <-sendFailure:
				return
			}

		}
	}()

	go func() {
		defer close(errors)
		defer close(sendFailure)
		for data := range dataChan {

			part, errUpload := uploadSinglePart(multi, len(parts)+1, data, retryCount)

			totalBytesUploaded = totalBytesUploaded + len(data)
			parts = append(parts, *part)

			log.Printf("%d parts of %s and ~%dMB of data has been uploaded",
				len(parts),
				multi.Key,
				totalBytesUploaded/(1024.0*1024.0))

			if errUpload != nil {
				sendFailure <- struct{}{}
				errors <- errUpload
				return
			}

			select {
			case err, _ := <-readFailure:
				if err != nil {
					return
				}
			default:
			}
		}
	}()

	for err := range errors {
		return nil, err
	}

	return parts, nil
}

func readSinglePart(reader io.Reader, chunkSizeInMB int) ([]byte, error) {
	data := make([]byte, 1024*1024*chunkSizeInMB)

	readLen, errRead := reader.Read(data)
	data = data[:readLen]

	return data, errRead
}

func uploadSinglePart(multipartSession *s3.Multi, partNum int, data []byte, retry int) (*s3.Part, error) {

	part, err := multipartSession.PutPart(partNum, bytes.NewReader(data))

	if err != nil {
		if retry > 0 {
			log.Printf("Part %d for %s failed. Retrying. Error: %v", partNum, multipartSession.Key, err)
			return uploadSinglePart(multipartSession, partNum, data, retry-1)
		} else {
			log.Printf("Part %d for %s failed. Error: %v", partNum, multipartSession.Key, err)
			return nil, err
		}
	}

	return &part, err
}
<commit_msg>Propagate error when multipart upload doesn't conclude successfully<commit_after>package s3

import (
	"bytes"
	"io"
	"log"

	"github.com/goamz/goamz/aws"
	"github.com/goamz/goamz/s3"
)

type S3Creds struct {
	AccessKey string
	SecretKey string
}

type S3MultipartUploadSession struct {
	creds         S3Creds
	s3Region      string
	s3Bucket      string
	chunkSizeInMB int
}

func CleanupChunks(s3AccessKey string, s3SecretKey string, s3Region string, s3Bucket string) {
	auth := aws.Auth{
		AccessKey: s3AccessKey,
		SecretKey: s3SecretKey}

	b := s3.New(auth, aws.Regions[s3Region]).Bucket(s3Bucket)

	multis, _, _ := b.ListMulti("", "")

	for _, m := range multis {
		log.Println("Removing part files for: ", m)
		m.Abort()
	}
}

func NewS3Creds(accessKey string, secretKey string) S3Creds {
	return S3Creds{AccessKey: accessKey, SecretKey: secretKey}
}

func NewS3MultipartUpload(s3AccessKey string,
	s3SecretKey string,
	s3Region string,
	s3Bucket string,
	chunkSizeInMB int) S3MultipartUploadSession {
	return S3MultipartUploadSession{s3Bucket: s3Bucket,
		s3Region:      s3Region,
		chunkSizeInMB: chunkSizeInMB,
		creds: S3Creds{
			AccessKey: s3AccessKey,
			SecretKey: s3SecretKey}}
}

func (s *S3MultipartUploadSession) awsAuth() aws.Auth {
	return aws.Auth{
		AccessKey: s.creds.AccessKey,
		SecretKey: s.creds.SecretKey}
}

func (s *S3MultipartUploadSession) getS3Bucket() *s3.Bucket {
	auth := s.awsAuth()
	return s3.New(auth, aws.Regions[s.s3Region]).Bucket(s.s3Bucket)
}

func (s *S3MultipartUploadSession) UploadMultiPart(reader io.Reader, s3Path string) error {

	bucket := s.getS3Bucket()
	multi, err := bucket.InitMulti(s3Path, "text/plain", s3.Private)

	if err != nil {
		return err
	}

	parts, err := s.uploadMultiPart(multi, reader)

	var errCleanup error = nil

	if err != nil {
		log.Printf("Multipart upload for %s failed, aborting: %v\n", s3Path, err)
		errCleanup = multi.Abort()
	} else {
		log.Printf("Multipart upload for %s successful, stitching the parts.\n", s3Path)
		errCleanup = multi.Complete(parts)
	}

	if errCleanup != nil {
		log.Println("Abort or complete for %s failed. You should cleanup the parts manually: %v. Original error %v\n", s3Path, errCleanup, err)
		return errCleanup
	}

	return err
}

func (s *S3MultipartUploadSession) uploadMultiPart(multi *s3.Multi, reader io.Reader) ([]s3.Part, error) {

	var parts []s3.Part
	var totalBytesUploaded = 0
	const retryCount = 3

	dataChan := make(chan []byte)
	readFailure := make(chan error)
	sendFailure := make(chan struct{})
	errors := make(chan error, 2)

	go func() {
		defer close(dataChan)
		defer close(readFailure)
		for {
			data, errRead := readSinglePart(reader, s.chunkSizeInMB)
			select {
			case dataChan <- data:
				if errRead != nil {
					if errRead != io.EOF {
						readFailure <- errRead
						errors <- errRead
					}
					return
				}
			case <-sendFailure:
				return
			}

		}
	}()

	go func() {
		defer close(errors)
		defer close(sendFailure)
		for data := range dataChan {

			part, errUpload := uploadSinglePart(multi, len(parts)+1, data, retryCount)

			totalBytesUploaded = totalBytesUploaded + len(data)
			parts = append(parts, *part)

			log.Printf("%d parts of %s and ~%dMB of data has been uploaded",
				len(parts),
				multi.Key,
				totalBytesUploaded/(1024.0*1024.0))

			if errUpload != nil {
				sendFailure <- struct{}{}
				errors <- errUpload
				return
			}

			select {
			case err, _ := <-readFailure:
				if err != nil {
					return
				}
			default:
			}
		}
	}()

	for err := range errors {
		return nil, err
	}

	return parts, nil
}

func readSinglePart(reader io.Reader, chunkSizeInMB int) ([]byte, error) {
	data := make([]byte, 1024*1024*chunkSizeInMB)

	readLen, errRead := reader.Read(data)
	data = data[:readLen]

	return data, errRead
}

func uploadSinglePart(multipartSession *s3.Multi, partNum int, data []byte, retry int) (*s3.Part, error) {

	part, err := multipartSession.PutPart(partNum, bytes.NewReader(data))

	if err != nil {
		if retry > 0 {
			log.Printf("Part %d for %s failed. Retrying. Error: %v", partNum, multipartSession.Key, err)
			return uploadSinglePart(multipartSession, partNum, data, retry-1)
		} else {
			log.Printf("Part %d for %s failed. Error: %v", partNum, multipartSession.Key, err)
			return nil, err
		}
	}

	return &part, err
}
<|endoftext|>


<commit_before>package datasource

import (
	"database/sql/driver"
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/araddon/dateparse"
	u "github.com/araddon/gou"
)

type TimeValue time.Time

func (m *TimeValue) MarshalJSON() ([]byte, error) {
	by, err := time.Time(*m).MarshalJSON()
	return by, err
}

func (m *TimeValue) UnmarshalJSON(data []byte) error {
	var t time.Time
	err := json.Unmarshal(data, &t)
	if err == nil {
		*m = TimeValue(t)
	}
	return err

}

func (m TimeValue) Value() (driver.Value, error) {
	u.Debugf("Value: %v", m)
	by, err := json.Marshal(time.Time(m))
	return by, err
}

func (m TimeValue) Time() time.Time {
	return time.Time(m)
}

func (m *TimeValue) Scan(src interface{}) error {
	//u.Debugf("scan: '%v'", src)
	var t time.Time
	switch val := src.(type) {
	case string:
		//u.Infof("trying to scan string: '%v'", val)
		t2, err := dateparse.ParseAny(val)
		if err == nil {
			*m = TimeValue(t2)
			return nil
		}
		//u.Infof("%v  %v", t2, err)
		err = json.Unmarshal([]byte(val), &t)
		if err == nil {
			*m = TimeValue(t)
		} else {
			u.Warnf("error? %v", err)
			return err
		}
	case []byte:
		t2, err := dateparse.ParseAny(string(val))
		if err == nil {
			*m = TimeValue(t2)
			return nil
		}
		err = json.Unmarshal(val, &t)
		if err == nil {
			*m = TimeValue(t)
		} else {
			return err
		}
	default:
		u.Warnf("unknown type: %T", m)
		return errors.New("Incompatible type for TimeValue")
	}
	return nil
}

func (m *TimeValue) Unmarshal(v interface{}) error {
	u.Warnf("wat? %T %v", v, v)
	//return json.Unmarshal([]byte(*m), v)
	return fmt.Errorf("not implemented")
}

type JsonWrapper json.RawMessage

func (m *JsonWrapper) MarshalJSON() ([]byte, error) { return *m, nil }

// Unmarshall bytes into this typed struct
func (m *JsonWrapper) UnmarshalJSON(data []byte) error {
	if m == nil {
		return errors.New("JsonWrapper must not be nil")
	}
	*m = append((*m)[0:0], data...)
	return nil

}

// This is the go sql/driver interface we need to implement to allow
// conversion back forth
func (m JsonWrapper) Value() (driver.Value, error) {
	var jsonRaw json.RawMessage
	err := m.Unmarshal(&jsonRaw)
	if err != nil {
		return []byte{}, err
	}
	return []byte(m), nil
}

func (m *JsonWrapper) Scan(src interface{}) error {
	var jsonBytes []byte
	switch src.(type) {
	case string:
		jsonBytes = []byte(src.(string))
	case []byte:
		jsonBytes = src.([]byte)
	default:
		return errors.New("Incompatible type for JsonWrapper")
	}
	*m = JsonWrapper(append((*m)[0:0], jsonBytes...))
	return nil
}

func (m *JsonWrapper) Unmarshal(v interface{}) error {
	return json.Unmarshal([]byte(*m), v)
}

type JsonHelperScannable u.JsonHelper

func (m *JsonHelperScannable) MarshalJSON() ([]byte, error) {
	return json.Marshal(u.JsonHelper(*m))
}

// Unmarshall bytes into this typed struct
func (m *JsonHelperScannable) UnmarshalJSON(data []byte) error {
	if m == nil {
		return errors.New("JsonHelperScannable must not be nil")
	}
	jh := make(u.JsonHelper)
	if err := json.Unmarshal(data, &jh); err != nil {
		return err
	}
	*m = JsonHelperScannable(jh)
	return nil

}

// This is the go sql/driver interface we need to implement to allow
// conversion back forth
func (m JsonHelperScannable) Value() (driver.Value, error) {
	jsonBytes, err := json.Marshal(u.JsonHelper(m))
	if err != nil {
		return []byte{}, err
	}
	return jsonBytes, nil
}

func (m *JsonHelperScannable) Scan(src interface{}) error {
	var jsonBytes []byte
	switch tv := src.(type) {
	case string:
		jsonBytes = []byte(tv)
	case []byte:
		jsonBytes = tv
	case nil:
		return nil
	default:
		return fmt.Errorf("Incompatible type:%T for JsonHelperScannable", src)
	}
	jh := make(u.JsonHelper)
	if err := json.Unmarshal(jsonBytes, &jh); err != nil {
		return err
	}
	*m = JsonHelperScannable(jh)
	return nil
}

// func (m *JsonHelperScannable) Unmarshal(v interface{}) error {
// 	return json.Unmarshal([]byte(*m), v)
// }

type StringArray []string

func (m *StringArray) MarshalJSON() ([]byte, error) {
	by, err := json.Marshal(*m)
	return by, err
}

func (m *StringArray) UnmarshalJSON(data []byte) error {
	var l []string
	err := json.Unmarshal(data, &l)
	if err != nil {
		return err
	}
	*m = StringArray(l)
	return nil
}

func (m StringArray) Value() (driver.Value, error) {
	by, err := json.Marshal(m)
	return by, err
}

func (m *StringArray) Scan(src interface{}) error {
	var srcBytes []byte
	switch val := src.(type) {
	case string:
		srcBytes = []byte(val)
	case []byte:
		srcBytes = val
	default:
		u.Warnf("unknown type: %T", src)
		return errors.New("Incompatible type for StringArray")
	}
	sa := make([]string, 0)
	err := json.Unmarshal(srcBytes, &sa)
	if err != nil {
		u.Warnf("error? %v", err)
		return err
	}
	*m = StringArray(sa)
	return nil
}
<commit_msg>support nil time<commit_after>package datasource

import (
	"database/sql/driver"
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/araddon/dateparse"
	u "github.com/araddon/gou"
)

type TimeValue time.Time

func (m *TimeValue) MarshalJSON() ([]byte, error) {
	by, err := time.Time(*m).MarshalJSON()
	return by, err
}

func (m *TimeValue) UnmarshalJSON(data []byte) error {
	var t time.Time
	err := json.Unmarshal(data, &t)
	if err == nil {
		*m = TimeValue(t)
	}
	return err

}

func (m TimeValue) Value() (driver.Value, error) {
	u.Debugf("Value: %v", m)
	by, err := json.Marshal(time.Time(m))
	return by, err
}

func (m TimeValue) Time() time.Time {
	return time.Time(m)
}

func (m *TimeValue) Scan(src interface{}) error {
	//u.Debugf("scan: '%v'", src)
	var t time.Time
	switch val := src.(type) {
	case string:
		//u.Infof("trying to scan string: '%v'", val)
		t2, err := dateparse.ParseAny(val)
		if err == nil {
			*m = TimeValue(t2)
			return nil
		}
		//u.Infof("%v  %v", t2, err)
		err = json.Unmarshal([]byte(val), &t)
		if err == nil {
			*m = TimeValue(t)
		} else {
			u.Warnf("error? %v", err)
			return err
		}
	case []byte:
		t2, err := dateparse.ParseAny(string(val))
		if err == nil {
			*m = TimeValue(t2)
			return nil
		}
		err = json.Unmarshal(val, &t)
		if err == nil {
			*m = TimeValue(t)
		} else {
			return err
		}
	case nil:
		return nil
	default:
		u.Warnf("unknown type: %T", m)
		return errors.New("Incompatible type for TimeValue")
	}
	return nil
}

func (m *TimeValue) Unmarshal(v interface{}) error {
	u.Warnf("wat? %T %v", v, v)
	//return json.Unmarshal([]byte(*m), v)
	return fmt.Errorf("not implemented")
}

type JsonWrapper json.RawMessage

func (m *JsonWrapper) MarshalJSON() ([]byte, error) { return *m, nil }

// Unmarshall bytes into this typed struct
func (m *JsonWrapper) UnmarshalJSON(data []byte) error {
	if m == nil {
		return errors.New("JsonWrapper must not be nil")
	}
	*m = append((*m)[0:0], data...)
	return nil

}

// This is the go sql/driver interface we need to implement to allow
// conversion back forth
func (m JsonWrapper) Value() (driver.Value, error) {
	var jsonRaw json.RawMessage
	err := m.Unmarshal(&jsonRaw)
	if err != nil {
		return []byte{}, err
	}
	return []byte(m), nil
}

func (m *JsonWrapper) Scan(src interface{}) error {
	var jsonBytes []byte
	switch src.(type) {
	case string:
		jsonBytes = []byte(src.(string))
	case []byte:
		jsonBytes = src.([]byte)
	default:
		return errors.New("Incompatible type for JsonWrapper")
	}
	*m = JsonWrapper(append((*m)[0:0], jsonBytes...))
	return nil
}

func (m *JsonWrapper) Unmarshal(v interface{}) error {
	return json.Unmarshal([]byte(*m), v)
}

type JsonHelperScannable u.JsonHelper

func (m *JsonHelperScannable) MarshalJSON() ([]byte, error) {
	return json.Marshal(u.JsonHelper(*m))
}

// Unmarshall bytes into this typed struct
func (m *JsonHelperScannable) UnmarshalJSON(data []byte) error {
	if m == nil {
		return errors.New("JsonHelperScannable must not be nil")
	}
	jh := make(u.JsonHelper)
	if err := json.Unmarshal(data, &jh); err != nil {
		return err
	}
	*m = JsonHelperScannable(jh)
	return nil

}

// This is the go sql/driver interface we need to implement to allow
// conversion back forth
func (m JsonHelperScannable) Value() (driver.Value, error) {
	jsonBytes, err := json.Marshal(u.JsonHelper(m))
	if err != nil {
		return []byte{}, err
	}
	return jsonBytes, nil
}

func (m *JsonHelperScannable) Scan(src interface{}) error {
	var jsonBytes []byte
	switch tv := src.(type) {
	case string:
		jsonBytes = []byte(tv)
	case []byte:
		jsonBytes = tv
	case nil:
		return nil
	default:
		return fmt.Errorf("Incompatible type:%T for JsonHelperScannable", src)
	}
	jh := make(u.JsonHelper)
	if err := json.Unmarshal(jsonBytes, &jh); err != nil {
		return err
	}
	*m = JsonHelperScannable(jh)
	return nil
}

// func (m *JsonHelperScannable) Unmarshal(v interface{}) error {
// 	return json.Unmarshal([]byte(*m), v)
// }

type StringArray []string

func (m *StringArray) MarshalJSON() ([]byte, error) {
	by, err := json.Marshal(*m)
	return by, err
}

func (m *StringArray) UnmarshalJSON(data []byte) error {
	var l []string
	err := json.Unmarshal(data, &l)
	if err != nil {
		return err
	}
	*m = StringArray(l)
	return nil
}

func (m StringArray) Value() (driver.Value, error) {
	by, err := json.Marshal(m)
	return by, err
}

func (m *StringArray) Scan(src interface{}) error {
	var srcBytes []byte
	switch val := src.(type) {
	case string:
		srcBytes = []byte(val)
	case []byte:
		srcBytes = val
	default:
		u.Warnf("unknown type: %T", src)
		return errors.New("Incompatible type for StringArray")
	}
	sa := make([]string, 0)
	err := json.Unmarshal(srcBytes, &sa)
	if err != nil {
		u.Warnf("error? %v", err)
		return err
	}
	*m = StringArray(sa)
	return nil
}
<|endoftext|>


<commit_before>package slackbot

import (
	"bufio"
	"math/rand"
	"os"
	"regexp"
	"strings"
)

var r_quote = regexp.MustCompile(`([^:]*):.*\/\/(.*)`)

type GoonQuote struct {
	File  string
	Quote string
}

func load_goon_quotes() ([]*GoonQuote, error) {
	f, e := os.Open(GOON_QUOTES_FILE)
	if e != nil {
		return nil, e
	}
	defer f.Close()

	var quotes []*GoonQuote
	s := bufio.NewScanner(f)
	for s.Scan() {
		q := parse_goon_quote(s.Text())
		if q != nil {
			quotes = append(quotes, q)
		}
	}

	if e = s.Err(); e != nil {
		return nil, e
	}

	return quotes, nil
}

func parse_goon_quote(line string) *GoonQuote {
	tmp := r_quote.FindStringSubmatch(line)
	if tmp == nil || len(tmp) != 3 {
		return nil
	}

	file := strings.TrimSpace(tmp[1])
	quote := strings.TrimSpace(tmp[2])
	if len(file) < 1 || len(quote) < 1 {
		return nil
	}

	return &GoonQuote{file, quote}
}

func (i *Instance) random_goon_quote() *GoonQuote {
	line := rand.Intn(len(i.goon))
	return i.goon[line]
}
<commit_msg>Easier format to handle for the goon_quotes file.<commit_after>package slackbot

import (
	"bufio"
	"math/rand"
	"os"
	"strings"
)

type GoonQuote struct {
	File  string
	Quote string
}

func load_goon_quotes() ([]*GoonQuote, error) {
	f, e := os.Open(GOON_QUOTES_FILE)
	if e != nil {
		return nil, e
	}
	defer f.Close()

	var quotes []*GoonQuote
	s := bufio.NewScanner(f)
	for s.Scan() {
		q := parse_goon_quote(s.Text())
		if q != nil {
			quotes = append(quotes, q)
		}
	}

	if e = s.Err(); e != nil {
		return nil, e
	}

	return quotes, nil
}
func parse_goon_quote(line string) *GoonQuote {
	tmp := strings.SplitN(line, " ", 2)
	if len(tmp) != 2 {
		return nil
	}
	quote := strings.TrimSpace(tmp[1])
	file := strings.TrimSpace(tmp[0])
	fparts := strings.SplitN(file, "goonstation", 2)
	file = fparts[1]

	return &GoonQuote{file, quote}
}
func (i *Instance) random_goon_quote() *GoonQuote {
	line := rand.Intn(len(i.goon))
	return i.goon[line]
}
<|endoftext|>


<commit_before>// Copyright © 2013 Steve Francia <spf@spf13.com>.
//
// 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.

// Commands similar to git, go tools and other modern CLI tools
// inspired by go, go-Commander, gh and subcommand

package cobra

import (
	"bytes"
	"fmt"
	flag "github.com/ogier/pflag"
	"os"
	"strings"
)

var _ = flag.ContinueOnError

type Flag interface {
	Args() []string
}

type Flags interface {
	Lookup(string) *Flag
	VisitAll(fn func(*Flag))
	Parse(arguments []string) error
}

// A Commander holds the configuration for the command line tool.
type Commander struct {
	// A Commander is also a Command for top level and global help & flags
	Command
	//ExitOnError, ContinueOnError or PanicOnError
	behavior flag.ErrorHandling

	args []string
}

func NewCommander() (c *Commander) {
	c = new(Commander)
	return
}

func (c *Commander) setFlagBehavior(b flag.ErrorHandling) error {
	if b == flag.ExitOnError || b == flag.ContinueOnError || b == flag.PanicOnError {
		c.behavior = b
		return nil
	}
	return fmt.Errorf("%v is not a valid behavior", b)
}

func (c *Commander) SetName(name string) {
	c.name = name
}

func (c *Commander) SetArgs(a []string) {
	c.args = a
}

func (c *Commander) Execute() {
	if len(c.args) == 0 {
		c.execute(os.Args[1:])
	} else {
		c.execute(c.args)
	}
}

// Command is just that, a command for your application.
// eg.  'go run' ... 'run' is the command. Cobra requires
// you to define the usage and description as part of your command
// definition to ensure usability.
type Command struct {
	// Name is the command name, usually the executable's name.
	name string
	// The one-line usage message.
	Use string
	// The short description shown in the 'help' output.
	Short string
	// The long message shown in the 'help <this-command>' output.
	Long string
	// Set of flags specific to this command.
	flags *flag.FlagSet
	// Set of flags children commands will inherit
	pflags *flag.FlagSet
	// Run runs the command.
	// The args are the arguments after the command name.
	Run func(cmd *Command, args []string)
	// Commands is the list of commands supported by this Commander program.
	commands []*Command
	// Parent Command for this command
	parent *Command
	// Commander
	//cmdr *Commander
	flagErrorBuf *bytes.Buffer
}

// find the target command given the args and command tree
func (c *Command) Find(args []string) (cmd *Command, a []string, err error) {
	if c == nil {
		return nil, nil, fmt.Errorf("Called find() on a nil Command")
	}

	validSubCommand := false
	if len(args) > 1 && c.HasSubCommands() {
		for _, cmd := range c.commands {
			if cmd.Name() == args[0] {
				validSubCommand = true
				return cmd.Find(args[1:])
			}
		}
	}
	if !validSubCommand && c.Runnable() {
		return c, args, nil
	}

	return nil, nil, nil
}

// execute the command determined by args and the command tree
func (c *Command) execute(args []string) (err error) {
	err = fmt.Errorf("unknown subcommand %q\nRun 'help' for usage.\n", args[0])

	if c == nil {
		return fmt.Errorf("Called Execute() on a nil Command")
	}

	cmd, a, e := c.Find(args)
	if e == nil {
		cmd.Flags().Parse(a)
		argWoFlags := cmd.Flags().Args()
		cmd.Run(cmd, argWoFlags)
		return nil
	}
	err = e
	return err
}

// Add one or many commands as children of this
func (c *Command) AddCommand(cmds ...*Command) {
	for i, x := range cmds {
		cmds[i].parent = c
		c.commands = append(c.commands, x)
	}
}

// The full usage for a given command (including parents)
func (c *Command) Usage(depth ...int) string {
	i := 0
	if len(depth) > 0 {
		i = depth[0]
	}

	if c.HasParent() {
		return c.parent.Usage(i+1) + " " + c.Use
	} else if i > 0 {
		return c.Name()
	} else {
		return c.Use
	}
}

// Usage prints the usage details to the standard output.
func (c *Command) PrintUsage() {
	if c.Runnable() {
		fmt.Printf("usage: %s\n\n", c.Usage())
	}

	fmt.Println(strings.Trim(c.Long, "\n"))
}

// Name returns the command's name: the first word in the use line.
func (c *Command) Name() string {
	if c.name != "" {
		return c.name
	}
	name := c.Use
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

// Determine if the command is itself runnable
func (c *Command) Runnable() bool {
	return c.Run != nil
}

// Determine if the command has children commands
func (c *Command) HasSubCommands() bool {
	return len(c.commands) > 0
}

// Determine if the command has children commands
func (c *Command) HasParent() bool {
	return c.parent != nil
}

// Get the Commands FlagSet
func (c *Command) Flags() *flag.FlagSet {
	if c.flags == nil {
		c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
		c.flags.SetOutput(c.flagErrorBuf)
	}
	return c.flags
}

// Get the Commands Persistent FlagSet
func (c *Command) PersistentFlags() *flag.FlagSet {
	if c.pflags == nil {
		c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
		c.pflags.SetOutput(c.flagErrorBuf)
	}
	return c.flags
}

// Intended for use in testing
func (c *Command) ResetFlags() {
	c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
	c.flags.SetOutput(c.flagErrorBuf)
	c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
	c.pflags.SetOutput(c.flagErrorBuf)
}

func (c *Command) HasFlags() bool {
	return hasFlags(c.flags)
}

func (c *Command) HasPersistentFlags() bool {
	return hasFlags(c.pflags)
}

// Is this set of flags not empty
func hasFlags(f *flag.FlagSet) bool {
	if f == nil {
		return false
	}
	if f.NFlag() != 0 {
		return true
	}
	return false
}

// Climbs up the command tree looking for matching flag
func (c *Command) Flag(name string) (flag *flag.Flag) {
	flag = c.Flags().Lookup(name)

	if flag == nil {
		flag = c.persistentFlag(name)
	}

	return
}

// recursively find matching persistent flag
func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
	if c.HasPersistentFlags() {
		flag = c.PersistentFlags().Lookup(name)
	}

	if flag == nil && c.HasParent() {
		flag = c.parent.persistentFlag(name)
	}
	return
}

// Parses persistent flag tree & local flags
func (c *Command) ParseFlags(args []string) (err error) {
	err = c.ParsePersistentFlags(args)
	if err != nil {
		return err
	}
	err = c.Flags().Parse(args)
	if err != nil {
		return err
	}
	return nil
}

// Climbs up the command tree parsing flags from top to bottom
func (c *Command) ParsePersistentFlags(args []string) (err error) {
	if !c.HasParent() || c.parent.PersistentFlags().Parsed() {
		err = c.PersistentFlags().Parse(args)
		if err != nil {
			return err
		}
	} else {
		err = c.parent.ParsePersistentFlags(args)
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Properly swallowing flag error messages<commit_after>// Copyright © 2013 Steve Francia <spf@spf13.com>.
//
// 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.

// Commands similar to git, go tools and other modern CLI tools
// inspired by go, go-Commander, gh and subcommand

package cobra

import (
	"bytes"
	"fmt"
	flag "github.com/ogier/pflag"
	"os"
	"strings"
)

var _ = flag.ContinueOnError

type Flag interface {
	Args() []string
}

type Flags interface {
	Lookup(string) *Flag
	VisitAll(fn func(*Flag))
	Parse(arguments []string) error
}

// A Commander holds the configuration for the command line tool.
type Commander struct {
	// A Commander is also a Command for top level and global help & flags
	Command
	//ExitOnError, ContinueOnError or PanicOnError
	behavior flag.ErrorHandling

	args []string
}

func NewCommander() (c *Commander) {
	c = new(Commander)
	return
}

func (c *Commander) setFlagBehavior(b flag.ErrorHandling) error {
	if b == flag.ExitOnError || b == flag.ContinueOnError || b == flag.PanicOnError {
		c.behavior = b
		return nil
	}
	return fmt.Errorf("%v is not a valid behavior", b)
}

func (c *Commander) SetName(name string) {
	c.name = name
}

func (c *Commander) SetArgs(a []string) {
	c.args = a
}

func (c *Commander) Execute() {
	if len(c.args) == 0 {
		c.execute(os.Args[1:])
	} else {
		c.execute(c.args)
	}
}

// Command is just that, a command for your application.
// eg.  'go run' ... 'run' is the command. Cobra requires
// you to define the usage and description as part of your command
// definition to ensure usability.
type Command struct {
	// Name is the command name, usually the executable's name.
	name string
	// The one-line usage message.
	Use string
	// The short description shown in the 'help' output.
	Short string
	// The long message shown in the 'help <this-command>' output.
	Long string
	// Set of flags specific to this command.
	flags *flag.FlagSet
	// Set of flags children commands will inherit
	pflags *flag.FlagSet
	// Run runs the command.
	// The args are the arguments after the command name.
	Run func(cmd *Command, args []string)
	// Commands is the list of commands supported by this Commander program.
	commands []*Command
	// Parent Command for this command
	parent *Command
	// Commander
	//cmdr *Commander
	flagErrorBuf *bytes.Buffer
}

// find the target command given the args and command tree
func (c *Command) Find(args []string) (cmd *Command, a []string, err error) {
	if c == nil {
		return nil, nil, fmt.Errorf("Called find() on a nil Command")
	}

	validSubCommand := false
	if len(args) > 1 && c.HasSubCommands() {
		for _, cmd := range c.commands {
			if cmd.Name() == args[0] {
				validSubCommand = true
				return cmd.Find(args[1:])
			}
		}
	}
	if !validSubCommand && c.Runnable() {
		return c, args, nil
	}

	return nil, nil, nil
}

// execute the command determined by args and the command tree
func (c *Command) execute(args []string) (err error) {
	err = fmt.Errorf("unknown subcommand %q\nRun 'help' for usage.\n", args[0])

	if c == nil {
		return fmt.Errorf("Called Execute() on a nil Command")
	}

	cmd, a, e := c.Find(args)
	if e == nil {
		cmd.Flags().Parse(a)
		argWoFlags := cmd.Flags().Args()
		cmd.Run(cmd, argWoFlags)
		return nil
	}
	err = e
	return err
}

// Add one or many commands as children of this
func (c *Command) AddCommand(cmds ...*Command) {
	for i, x := range cmds {
		cmds[i].parent = c
		c.commands = append(c.commands, x)
	}
}

// The full usage for a given command (including parents)
func (c *Command) Usage(depth ...int) string {
	i := 0
	if len(depth) > 0 {
		i = depth[0]
	}

	if c.HasParent() {
		return c.parent.Usage(i+1) + " " + c.Use
	} else if i > 0 {
		return c.Name()
	} else {
		return c.Use
	}
}

// Usage prints the usage details to the standard output.
func (c *Command) PrintUsage() {
	if c.Runnable() {
		fmt.Printf("usage: %s\n\n", c.Usage())
	}

	fmt.Println(strings.Trim(c.Long, "\n"))
}

// Name returns the command's name: the first word in the use line.
func (c *Command) Name() string {
	if c.name != "" {
		return c.name
	}
	name := c.Use
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

// Determine if the command is itself runnable
func (c *Command) Runnable() bool {
	return c.Run != nil
}

// Determine if the command has children commands
func (c *Command) HasSubCommands() bool {
	return len(c.commands) > 0
}

// Determine if the command has children commands
func (c *Command) HasParent() bool {
	return c.parent != nil
}

// Get the Commands FlagSet
func (c *Command) Flags() *flag.FlagSet {
	if c.flags == nil {
		c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
		if c.flagErrorBuf == nil {
			c.flagErrorBuf = new(bytes.Buffer)
		}
		c.flags.SetOutput(c.flagErrorBuf)
	}
	return c.flags
}

// Get the Commands Persistent FlagSet
func (c *Command) PersistentFlags() *flag.FlagSet {
	if c.pflags == nil {
		c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
		if c.flagErrorBuf == nil {
			c.flagErrorBuf = new(bytes.Buffer)
		}
		c.pflags.SetOutput(c.flagErrorBuf)
	}
	return c.flags
}

// Intended for use in testing
func (c *Command) ResetFlags() {
	c.flagErrorBuf = new(bytes.Buffer)
	c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
	c.flags.SetOutput(c.flagErrorBuf)
	c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
	c.pflags.SetOutput(c.flagErrorBuf)
}

func (c *Command) HasFlags() bool {
	return hasFlags(c.flags)
}

func (c *Command) HasPersistentFlags() bool {
	return hasFlags(c.pflags)
}

// Is this set of flags not empty
func hasFlags(f *flag.FlagSet) bool {
	if f == nil {
		return false
	}
	if f.NFlag() != 0 {
		return true
	}
	return false
}

// Climbs up the command tree looking for matching flag
func (c *Command) Flag(name string) (flag *flag.Flag) {
	flag = c.Flags().Lookup(name)

	if flag == nil {
		flag = c.persistentFlag(name)
	}

	return
}

// recursively find matching persistent flag
func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
	if c.HasPersistentFlags() {
		flag = c.PersistentFlags().Lookup(name)
	}

	if flag == nil && c.HasParent() {
		flag = c.parent.persistentFlag(name)
	}
	return
}

// Parses persistent flag tree & local flags
func (c *Command) ParseFlags(args []string) (err error) {
	err = c.ParsePersistentFlags(args)
	if err != nil {
		return err
	}
	err = c.Flags().Parse(args)
	if err != nil {
		return err
	}
	return nil
}

// Climbs up the command tree parsing flags from top to bottom
func (c *Command) ParsePersistentFlags(args []string) (err error) {
	if !c.HasParent() || c.parent.PersistentFlags().Parsed() {
		err = c.PersistentFlags().Parse(args)
		if err != nil {
			return err
		}
	} else {
		err = c.parent.ParsePersistentFlags(args)
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package multiaddr

import (
	"encoding/binary"
	"fmt"
	"net"
	"strconv"
	"strings"
)

func stringToBytes(s string) ([]byte, error) {
	b := []byte{}
	sp := strings.Split(s, "/")

	if sp[0] != "" {
		return nil, fmt.Errorf("invalid multiaddr, must begin with /")
	}

	// consume first empty elem
	sp = sp[1:]

	for len(sp) > 0 {
		p := ProtocolWithName(sp[0])
		if p == nil {
			return nil, fmt.Errorf("no protocol with name %s", sp[0])
		}
		b = append(b, byte(p.Code))

		a := addressStringToBytes(p, sp[1])
		b = append(b, a...)

		sp = sp[2:]
	}
	return b, nil
}

func bytesToString(b []byte) (ret string, err error) {
	// panic handler, in case we try accessing bytes incorrectly.
	defer func() {
		if e := recover(); e != nil {
			ret = ""
			err = e.(error)
		}
	}()

	s := ""

	for len(b) > 0 {
		p := ProtocolWithCode(int(b[0]))
		if p == nil {
			return "", fmt.Errorf("no protocol with code %d", b[0])
		}
		s = strings.Join([]string{s, "/", p.Name}, "")
		b = b[1:]

		a := addressBytesToString(p, b[:(p.Size/8)])
		if len(a) > 0 {
			s = strings.Join([]string{s, "/", a}, "")
		}
		b = b[(p.Size / 8):]
	}

	return s, nil
}

func addressStringToBytes(p *Protocol, s string) []byte {
	switch p.Code {

	// ipv4,6
	case 4, 41:
		return net.ParseIP(s).To4()

	// tcp udp dccp sctp
	case 6, 17, 33, 132:
		b := make([]byte, 2)
		i, err := strconv.Atoi(s)
		if err == nil {
			binary.BigEndian.PutUint16(b, uint16(i))
		}
		return b
	}

	return []byte{}
}

func addressBytesToString(p *Protocol, b []byte) string {
	switch p.Code {

	// ipv4,6
	case 4, 41:
		return net.IP(b).String()

	// tcp udp dccp sctp
	case 6, 17, 33, 132:
		i := binary.BigEndian.Uint16(b)
		return strconv.Itoa(int(i))
	}

	return ""
}
<commit_msg>use constants, fix ipv6 bug<commit_after>package multiaddr

import (
	"encoding/binary"
	"fmt"
	"net"
	"strconv"
	"strings"
)

func stringToBytes(s string) ([]byte, error) {
	b := []byte{}
	sp := strings.Split(s, "/")

	if sp[0] != "" {
		return nil, fmt.Errorf("invalid multiaddr, must begin with /")
	}

	// consume first empty elem
	sp = sp[1:]

	for len(sp) > 0 {
		p := ProtocolWithName(sp[0])
		if p == nil {
			return nil, fmt.Errorf("no protocol with name %s", sp[0])
		}
		b = append(b, byte(p.Code))

		a := addressStringToBytes(p, sp[1])
		b = append(b, a...)

		sp = sp[2:]
	}
	return b, nil
}

func bytesToString(b []byte) (ret string, err error) {
	// panic handler, in case we try accessing bytes incorrectly.
	defer func() {
		if e := recover(); e != nil {
			ret = ""
			err = e.(error)
		}
	}()

	s := ""

	for len(b) > 0 {
		p := ProtocolWithCode(int(b[0]))
		if p == nil {
			return "", fmt.Errorf("no protocol with code %d", b[0])
		}
		s = strings.Join([]string{s, "/", p.Name}, "")
		b = b[1:]

		a := addressBytesToString(p, b[:(p.Size/8)])
		if len(a) > 0 {
			s = strings.Join([]string{s, "/", a}, "")
		}
		b = b[(p.Size / 8):]
	}

	return s, nil
}

func addressStringToBytes(p *Protocol, s string) []byte {
	switch p.Code {

	case P_IP4: // ipv4
		return net.ParseIP(s).To4()

	case P_IP6: // ipv6
		return net.ParseIP(s).To16()

	// tcp udp dccp sctp
	case P_TCP, P_UDP, P_DCCP, P_SCTP:
		b := make([]byte, 2)
		i, err := strconv.Atoi(s)
		if err == nil {
			binary.BigEndian.PutUint16(b, uint16(i))
		}
		return b
	}

	return []byte{}
}

func addressBytesToString(p *Protocol, b []byte) string {
	switch p.Code {

	// ipv4,6
	case P_IP4, P_IP6:
		return net.IP(b).String()

	// tcp udp dccp sctp
	case P_TCP, P_UDP, P_DCCP, P_SCTP:
		i := binary.BigEndian.Uint16(b)
		return strconv.Itoa(int(i))
	}

	return ""
}
<|endoftext|>


<commit_before>package gmf

/*

#cgo pkg-config: libavcodec

#include <stdlib.h>
#include "libavcodec/avcodec.h"
#include "libavutil/pixfmt.h"

*/
import "C"

import (
	"errors"
	"fmt"
	"unsafe"
)

var (
	AVMEDIA_TYPE_AUDIO int32 = C.AVMEDIA_TYPE_AUDIO
	AVMEDIA_TYPE_VIDEO int32 = C.AVMEDIA_TYPE_VIDEO

	AV_PIX_FMT_BGR24    int32 = C.AV_PIX_FMT_BGR24
	AV_PIX_FMT_GRAY8    int32 = C.AV_PIX_FMT_GRAY8
	AV_PIX_FMT_RGB24    int32 = C.AV_PIX_FMT_RGB24
	AV_PIX_FMT_YUV410P  int32 = C.AV_PIX_FMT_YUV410P
	AV_PIX_FMT_YUV411P  int32 = C.AV_PIX_FMT_YUV411P
	AV_PIX_FMT_YUV420P  int32 = C.AV_PIX_FMT_YUV420P
	AV_PIX_FMT_YUV422P  int32 = C.AV_PIX_FMT_YUV422P
	AV_PIX_FMT_YUV444P  int32 = C.AV_PIX_FMT_YUV444P
	AV_PIX_FMT_YUVJ420P int32 = C.AV_PIX_FMT_YUVJ420P
	AV_PIX_FMT_YUYV422  int32 = C.AV_PIX_FMT_YUYV422
	AV_PIX_FMT_NONE     int32 = C.AV_PIX_FMT_NONE

	FF_PROFILE_MPEG4_SIMPLE                    int = C.FF_PROFILE_MPEG4_SIMPLE
	FF_PROFILE_MPEG4_SIMPLE_SCALABLE           int = C.FF_PROFILE_MPEG4_SIMPLE_SCALABLE
	FF_PROFILE_MPEG4_CORE                      int = C.FF_PROFILE_MPEG4_CORE
	FF_PROFILE_MPEG4_MAIN                      int = C.FF_PROFILE_MPEG4_MAIN
	FF_PROFILE_MPEG4_N_BIT                     int = C.FF_PROFILE_MPEG4_N_BIT
	FF_PROFILE_MPEG4_SCALABLE_TEXTURE          int = C.FF_PROFILE_MPEG4_SCALABLE_TEXTURE
	FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION     int = C.FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION
	FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE    int = C.FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE
	FF_PROFILE_MPEG4_HYBRID                    int = C.FF_PROFILE_MPEG4_HYBRID
	FF_PROFILE_MPEG4_ADVANCED_REAL_TIME        int = C.FF_PROFILE_MPEG4_ADVANCED_REAL_TIME
	FF_PROFILE_MPEG4_CORE_SCALABLE             int = C.FF_PROFILE_MPEG4_CORE_SCALABLE
	FF_PROFILE_MPEG4_ADVANCED_CODING           int = C.FF_PROFILE_MPEG4_ADVANCED_CODING
	FF_PROFILE_MPEG4_ADVANCED_CORE             int = C.FF_PROFILE_MPEG4_ADVANCED_CORE
	FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE int = C.FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE
	FF_PROFILE_MPEG4_SIMPLE_STUDIO             int = C.FF_PROFILE_MPEG4_SIMPLE_STUDIO
	FF_PROFILE_MPEG4_ADVANCED_SIMPLE           int = C.FF_PROFILE_MPEG4_ADVANCED_SIMPLE

	AV_NOPTS_VALUE int64 = C.AV_NOPTS_VALUE
)

func init() {
	C.avcodec_register_all()
	InitDesc()
}

type Codec struct {
	avCodec *C.struct_AVCodec
	CgoMemoryManage
}

func FindDecoder(i interface{}) (*Codec, error) {
	var avc *C.struct_AVCodec

	switch t := i.(type) {
	case string:
		cname := C.CString(i.(string))
		defer C.free(unsafe.Pointer(cname))

		avc = C.avcodec_find_decoder_by_name(cname)
		break

	case int:
		avc = C.avcodec_find_decoder(uint32(i.(int)))
		break

	default:
		return nil, errors.New(fmt.Sprintf("Unable to find codec, unexpected arguments type '%v'", t))
	}

	if avc == nil {
		return nil, errors.New(fmt.Sprintf("Unable to find codec by value '%v'", i))
	}

	return &Codec{avCodec: avc}, nil
}

func FindEncoder(i interface{}) (*Codec, error) {
	var avc *C.struct_AVCodec

	switch t := i.(type) {
	case string:
		cname := C.CString(i.(string))
		defer C.free(unsafe.Pointer(cname))

		avc = C.avcodec_find_encoder_by_name(cname)
		break

	case int:
		avc = C.avcodec_find_encoder(uint32(i.(int)))
		break

	default:
		return nil, errors.New(fmt.Sprintf("Unable to find codec, unexpected arguments type '%v'", t))
	}

	if avc == nil {
		return nil, errors.New(fmt.Sprintf("Unable to find codec by value '%v'", i))
	}

	return &Codec{avCodec: avc}, nil
}

func (this *Codec) Free() {
	//nothing to do
}
func (this *Codec) Id() int {
	return int(this.avCodec.id)
}

func (this *Codec) Name() string {
	return C.GoString(this.avCodec.name)
}

func (this *Codec) LongName() string {
	return C.GoString(this.avCodec.long_name)
}

func (this *Codec) Type() int {
	// > ...field names that are keywords in Go can be
	// > accessed by prefixing them with an underscore
	return int(this.avCodec._type)
}

func (this *Codec) IsExperimental() bool {
	return bool((this.avCodec.capabilities & C.CODEC_CAP_EXPERIMENTAL) != 0)
}
<commit_msg>add more codec profile constants<commit_after>package gmf

/*

#cgo pkg-config: libavcodec

#include <stdlib.h>
#include "libavcodec/avcodec.h"
#include "libavutil/pixfmt.h"

*/
import "C"

import (
	"errors"
	"fmt"
	"unsafe"
)

var (
	AVMEDIA_TYPE_AUDIO int32 = C.AVMEDIA_TYPE_AUDIO
	AVMEDIA_TYPE_VIDEO int32 = C.AVMEDIA_TYPE_VIDEO

	AV_PIX_FMT_BGR24    int32 = C.AV_PIX_FMT_BGR24
	AV_PIX_FMT_GRAY8    int32 = C.AV_PIX_FMT_GRAY8
	AV_PIX_FMT_RGB24    int32 = C.AV_PIX_FMT_RGB24
	AV_PIX_FMT_YUV410P  int32 = C.AV_PIX_FMT_YUV410P
	AV_PIX_FMT_YUV411P  int32 = C.AV_PIX_FMT_YUV411P
	AV_PIX_FMT_YUV420P  int32 = C.AV_PIX_FMT_YUV420P
	AV_PIX_FMT_YUV422P  int32 = C.AV_PIX_FMT_YUV422P
	AV_PIX_FMT_YUV444P  int32 = C.AV_PIX_FMT_YUV444P
	AV_PIX_FMT_YUVJ420P int32 = C.AV_PIX_FMT_YUVJ420P
	AV_PIX_FMT_YUYV422  int32 = C.AV_PIX_FMT_YUYV422
	AV_PIX_FMT_NONE     int32 = C.AV_PIX_FMT_NONE

	FF_PROFILE_AAC_MAIN      int = C.FF_PROFILE_AAC_MAIN
	FF_PROFILE_AAC_LOW       int = C.FF_PROFILE_AAC_LOW
	FF_PROFILE_AAC_SSR       int = C.FF_PROFILE_AAC_SSR
	FF_PROFILE_AAC_LTP       int = C.FF_PROFILE_AAC_LTP
	FF_PROFILE_AAC_HE        int = C.FF_PROFILE_AAC_HE
	FF_PROFILE_AAC_HE_V2     int = C.FF_PROFILE_AAC_HE_V2
	FF_PROFILE_AAC_LD        int = C.FF_PROFILE_AAC_LD
	FF_PROFILE_AAC_ELD       int = C.FF_PROFILE_AAC_ELD
	FF_PROFILE_MPEG2_AAC_LOW int = C.FF_PROFILE_MPEG2_AAC_LOW
	FF_PROFILE_MPEG2_AAC_HE  int = C.FF_PROFILE_MPEG2_AAC_HE

	FF_PROFILE_DTS         int = C.FF_PROFILE_DTS
	FF_PROFILE_DTS_ES      int = C.FF_PROFILE_DTS_ES
	FF_PROFILE_DTS_96_24   int = C.FF_PROFILE_DTS_96_24
	FF_PROFILE_DTS_HD_HRA  int = C.FF_PROFILE_DTS_HD_HRA
	FF_PROFILE_DTS_HD_MA   int = C.FF_PROFILE_DTS_HD_MA
	FF_PROFILE_DTS_EXPRESS int = C.FF_PROFILE_DTS_EXPRESS

	FF_PROFILE_MPEG2_422          int = C.FF_PROFILE_MPEG2_422
	FF_PROFILE_MPEG2_HIGH         int = C.FF_PROFILE_MPEG2_HIGH
	FF_PROFILE_MPEG2_SS           int = C.FF_PROFILE_MPEG2_SS
	FF_PROFILE_MPEG2_SNR_SCALABLE int = C.FF_PROFILE_MPEG2_SNR_SCALABLE
	FF_PROFILE_MPEG2_MAIN         int = C.FF_PROFILE_MPEG2_MAIN
	FF_PROFILE_MPEG2_SIMPLE       int = C.FF_PROFILE_MPEG2_SIMPLE

	FF_PROFILE_H264_BASELINE            int = C.FF_PROFILE_H264_BASELINE
	FF_PROFILE_H264_MAIN                int = C.FF_PROFILE_H264_MAIN
	FF_PROFILE_H264_EXTENDED            int = C.FF_PROFILE_H264_EXTENDED
	FF_PROFILE_H264_HIGH                int = C.FF_PROFILE_H264_HIGH
	FF_PROFILE_H264_HIGH_10             int = C.FF_PROFILE_H264_HIGH_10
	FF_PROFILE_H264_HIGH_422            int = C.FF_PROFILE_H264_HIGH_422
	FF_PROFILE_H264_HIGH_444            int = C.FF_PROFILE_H264_HIGH_444
	FF_PROFILE_H264_HIGH_444_PREDICTIVE int = C.FF_PROFILE_H264_HIGH_444_PREDICTIVE
	FF_PROFILE_H264_CAVLC_444           int = C.FF_PROFILE_H264_CAVLC_444

	FF_PROFILE_VC1_SIMPLE   int = C.FF_PROFILE_VC1_SIMPLE
	FF_PROFILE_VC1_MAIN     int = C.FF_PROFILE_VC1_MAIN
	FF_PROFILE_VC1_COMPLEX  int = C.FF_PROFILE_VC1_COMPLEX
	FF_PROFILE_VC1_ADVANCED int = C.FF_PROFILE_VC1_ADVANCED

	FF_PROFILE_MPEG4_SIMPLE                    int = C.FF_PROFILE_MPEG4_SIMPLE
	FF_PROFILE_MPEG4_SIMPLE_SCALABLE           int = C.FF_PROFILE_MPEG4_SIMPLE_SCALABLE
	FF_PROFILE_MPEG4_CORE                      int = C.FF_PROFILE_MPEG4_CORE
	FF_PROFILE_MPEG4_MAIN                      int = C.FF_PROFILE_MPEG4_MAIN
	FF_PROFILE_MPEG4_N_BIT                     int = C.FF_PROFILE_MPEG4_N_BIT
	FF_PROFILE_MPEG4_SCALABLE_TEXTURE          int = C.FF_PROFILE_MPEG4_SCALABLE_TEXTURE
	FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION     int = C.FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION
	FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE    int = C.FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE
	FF_PROFILE_MPEG4_HYBRID                    int = C.FF_PROFILE_MPEG4_HYBRID
	FF_PROFILE_MPEG4_ADVANCED_REAL_TIME        int = C.FF_PROFILE_MPEG4_ADVANCED_REAL_TIME
	FF_PROFILE_MPEG4_CORE_SCALABLE             int = C.FF_PROFILE_MPEG4_CORE_SCALABLE
	FF_PROFILE_MPEG4_ADVANCED_CODING           int = C.FF_PROFILE_MPEG4_ADVANCED_CODING
	FF_PROFILE_MPEG4_ADVANCED_CORE             int = C.FF_PROFILE_MPEG4_ADVANCED_CORE
	FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE int = C.FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE
	FF_PROFILE_MPEG4_SIMPLE_STUDIO             int = C.FF_PROFILE_MPEG4_SIMPLE_STUDIO
	FF_PROFILE_MPEG4_ADVANCED_SIMPLE           int = C.FF_PROFILE_MPEG4_ADVANCED_SIMPLE

	AV_NOPTS_VALUE int64 = C.AV_NOPTS_VALUE

	FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0  int = C.FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0
	FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1  int = C.FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1
	FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION int = C.FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION
	FF_PROFILE_JPEG2000_DCINEMA_2K             int = C.FF_PROFILE_JPEG2000_DCINEMA_2K
	FF_PROFILE_JPEG2000_DCINEMA_4K             int = C.FF_PROFILE_JPEG2000_DCINEMA_4K

	FF_PROFILE_VP9_0 int = C.FF_PROFILE_VP9_0
	FF_PROFILE_VP9_1 int = C.FF_PROFILE_VP9_1
	FF_PROFILE_VP9_2 int = C.FF_PROFILE_VP9_2
	FF_PROFILE_VP9_3 int = C.FF_PROFILE_VP9_3

	FF_PROFILE_HEVC_MAIN               int = C.FF_PROFILE_HEVC_MAIN
	FF_PROFILE_HEVC_MAIN_10            int = C.FF_PROFILE_HEVC_MAIN_10
	FF_PROFILE_HEVC_MAIN_STILL_PICTURE int = C.FF_PROFILE_HEVC_MAIN_STILL_PICTURE
	FF_PROFILE_HEVC_REXT               int = C.FF_PROFILE_HEVC_REXT
)

func init() {
	C.avcodec_register_all()
	InitDesc()
}

type Codec struct {
	avCodec *C.struct_AVCodec
	CgoMemoryManage
}

func FindDecoder(i interface{}) (*Codec, error) {
	var avc *C.struct_AVCodec

	switch t := i.(type) {
	case string:
		cname := C.CString(i.(string))
		defer C.free(unsafe.Pointer(cname))

		avc = C.avcodec_find_decoder_by_name(cname)
		break

	case int:
		avc = C.avcodec_find_decoder(uint32(i.(int)))
		break

	default:
		return nil, errors.New(fmt.Sprintf("Unable to find codec, unexpected arguments type '%v'", t))
	}

	if avc == nil {
		return nil, errors.New(fmt.Sprintf("Unable to find codec by value '%v'", i))
	}

	return &Codec{avCodec: avc}, nil
}

func FindEncoder(i interface{}) (*Codec, error) {
	var avc *C.struct_AVCodec

	switch t := i.(type) {
	case string:
		cname := C.CString(i.(string))
		defer C.free(unsafe.Pointer(cname))

		avc = C.avcodec_find_encoder_by_name(cname)
		break

	case int:
		avc = C.avcodec_find_encoder(uint32(i.(int)))
		break

	default:
		return nil, errors.New(fmt.Sprintf("Unable to find codec, unexpected arguments type '%v'", t))
	}

	if avc == nil {
		return nil, errors.New(fmt.Sprintf("Unable to find codec by value '%v'", i))
	}

	return &Codec{avCodec: avc}, nil
}

func (this *Codec) Free() {
	//nothing to do
}
func (this *Codec) Id() int {
	return int(this.avCodec.id)
}

func (this *Codec) Name() string {
	return C.GoString(this.avCodec.name)
}

func (this *Codec) LongName() string {
	return C.GoString(this.avCodec.long_name)
}

func (this *Codec) Type() int {
	// > ...field names that are keywords in Go can be
	// > accessed by prefixing them with an underscore
	return int(this.avCodec._type)
}

func (this *Codec) IsExperimental() bool {
	return bool((this.avCodec.capabilities & C.CODEC_CAP_EXPERIMENTAL) != 0)
}
<|endoftext|>


<commit_before>package main

/// For Avent of Code
/// http://adventofcode.com/day/1/
/// Stanley Zheng

import (
	"bytes"
	"fmt"
	"io/ioutil"
)

var blank = []byte("")
var upLevel = []byte("(")
var downlevel = []byte(")")

// Count the number of floors using string replacement
// Count the difference
func main() {

	file, err := ioutil.ReadFile("../input.txt")
	if err != nil {
		fmt.Println("file can't be read")
	}

	up := bytes.Replace(file, downlevel, blank, -1)
	down := bytes.Replace(file, upLevel, blank, -1)
	fmt.Printf("Santa went up %d floors and down %d floors and ended up on the %d floor", len(up), len(down), len(up)-len(down))

}
<commit_msg>part 1 refactor<commit_after>package main

/// For Avent of Code
/// http://adventofcode.com/day/1/
/// Stanley Zheng

import (
	"bytes"
	"fmt"
	"io/ioutil"
)

var blank = []byte("")
var upLevel = []byte("(")
var downlevel = []byte(")")

// Count the number of floors using string replacement
// Count the difference
func main() {
	part1()
}

func part1() {
	file, err := ioutil.ReadFile("../input.txt")
	if err != nil {
		fmt.Println("file can't be read")
	}

	up := bytes.Replace(file, downlevel, blank, -1)
	down := bytes.Replace(file, upLevel, blank, -1)
	fmt.Printf("Santa went up %d floors and down %d floors and ended up on the %d floor", len(up), len(down), len(up)-len(down))

}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"regexp"

	"github.com/fatih/color"
)

var (
	numbers = color.New(color.FgRed).SprintFunc()
	strings = color.New(color.FgBlue).SprintFunc()
	bools   = color.New(color.FgMagenta).SprintFunc()
	arrays  = color.New(color.FgGreen).SprintFunc()
	hashes  = color.New(color.FgCyan).SprintFunc()
	nulls   = color.New(color.FgYellow).SprintFunc()
)

func colorize(blob []byte) []byte {
	blob = replaceArrays(blob) //must be first because colors contain [,]
	blob = replaceStrings(blob)
	blob = replaceNumbers(blob)
	blob = replaceBooleans(blob)
	blob = replaceHashes(blob)
	return replaceNulls(blob)
}

func replaceStrings(blob []byte) []byte {
	re, err := regexp.Compile(`"(?U)(.*)"`)
	if err != nil {
		log.Fatal(err)
	}
	color := strings(`"$1"`)
	return re.ReplaceAll(blob, []byte(color))
}

func replaceNumbers(blob []byte) []byte {
	re, err := regexp.Compile("(-?\\d+\\.?\\d*)(,?\\s*\n)")
	if err != nil {
		log.Fatal(err)
	}
	color := numbers("$1")
	return re.ReplaceAll(blob, []byte(color+"$2"))
}

func replaceBooleans(blob []byte) []byte {
	re, err := regexp.Compile("(true|false)(,?\\s*\n)")
	if err != nil {
		log.Fatal(err)
	}
	color := bools("$1")
	return re.ReplaceAll(blob, []byte(color+"$2"))
}

func replaceArrays(blob []byte) []byte {
	re, err := regexp.Compile("(\\s*)(\\[|\\])(,?\\s*(:?\n|$))")
	if err != nil {
		log.Fatal(err)
	}
	color := arrays("$2")
	return re.ReplaceAll(blob, []byte("$1"+color+"$3"))
}

func replaceHashes(blob []byte) []byte {
	re, err := regexp.Compile("(\\s*)({|})(,?\\s*(?:\n|$))")
	if err != nil {
		log.Fatal(err)
	}
	color := hashes("$2")
	return re.ReplaceAll(blob, []byte("$1"+color+"$3"))
}

func replaceNulls(blob []byte) []byte {
	re, err := regexp.Compile("null(,?\\s*\n)")
	if err != nil {
		log.Fatal(err)
	}
	color := nulls("null")
	return re.ReplaceAll(blob, []byte(color+"$1"))
}
<commit_msg>Fix regex for arrays and hashes<commit_after>package main

import (
	"log"
	"regexp"

	"github.com/fatih/color"
)

var (
	numbers = color.New(color.FgRed).SprintFunc()
	strings = color.New(color.FgBlue).SprintFunc()
	bools   = color.New(color.FgMagenta).SprintFunc()
	arrays  = color.New(color.FgGreen).SprintFunc()
	hashes  = color.New(color.FgCyan).SprintFunc()
	nulls   = color.New(color.FgYellow).SprintFunc()
)

func colorize(blob []byte) []byte {
	blob = replaceArrays(blob) //must be first because colors contain [,]
	blob = replaceStrings(blob)
	blob = replaceNumbers(blob)
	blob = replaceBooleans(blob)
	blob = replaceHashes(blob)
	return replaceNulls(blob)
}

func replaceStrings(blob []byte) []byte {
	re, err := regexp.Compile(`"(?U)(.*)"`)
	if err != nil {
		log.Fatal(err)
	}
	color := strings(`"$1"`)
	return re.ReplaceAll(blob, []byte(color))
}

func replaceNumbers(blob []byte) []byte {
	re, err := regexp.Compile("(-?\\d+\\.?\\d*)(,?\\s*\n)")
	if err != nil {
		log.Fatal(err)
	}
	color := numbers("$1")
	return re.ReplaceAll(blob, []byte(color+"$2"))
}

func replaceBooleans(blob []byte) []byte {
	re, err := regexp.Compile("(true|false)(,?\\s*\n)")
	if err != nil {
		log.Fatal(err)
	}
	color := bools("$1")
	return re.ReplaceAll(blob, []byte(color+"$2"))
}

func replaceArrays(blob []byte) []byte {
	re, err := regexp.Compile("(\\s*)(\\[\\]|\\[|\\])(,?\\s*(:?\n|$))")
	if err != nil {
		log.Fatal(err)
	}
	color := arrays("$2")
	return re.ReplaceAll(blob, []byte("$1"+color+"$3"))
}

func replaceHashes(blob []byte) []byte {
	re, err := regexp.Compile("(\\s*)({}|{|})(,?\\s*(?:\n|$))")
	if err != nil {
		log.Fatal(err)
	}
	color := hashes("$2")
	return re.ReplaceAll(blob, []byte("$1"+color+"$3"))
}

func replaceNulls(blob []byte) []byte {
	re, err := regexp.Compile("null(,?\\s*\n)")
	if err != nil {
		log.Fatal(err)
	}
	color := nulls("null")
	return re.ReplaceAll(blob, []byte(color+"$1"))
}
<|endoftext|>


<commit_before>package color

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"sync"

	"github.com/mattn/go-colorable"
	"github.com/mattn/go-isatty"
)

// NoColor defines if the output is colorized or not. It's dynamically set to
// false or true based on the stdout's file descriptor referring to a terminal
// or not. This is a global option and affects all colors. For more control
// over each color block use the methods DisableColor() individually.
var NoColor = !isatty.IsTerminal(os.Stdout.Fd())

// Color defines a custom color object which is defined by SGR parameters.
type Color struct {
	params  []Attribute
	noColor *bool
}

// Attribute defines a single SGR Code
type Attribute int

const escape = "\x1b"

// Base attributes
const (
	Reset Attribute = iota
	Bold
	Faint
	Italic
	Underline
	BlinkSlow
	BlinkRapid
	ReverseVideo
	Concealed
	CrossedOut
)

// Foreground text colors
const (
	FgBlack Attribute = iota + 30
	FgRed
	FgGreen
	FgYellow
	FgBlue
	FgMagenta
	FgCyan
	FgWhite
)

// Foreground Hi-Intensity text colors
const (
	FgHiBlack Attribute = iota + 90
	FgHiRed
	FgHiGreen
	FgHiYellow
	FgHiBlue
	FgHiMagenta
	FgHiCyan
	FgHiWhite
)

// Background text colors
const (
	BgBlack Attribute = iota + 40
	BgRed
	BgGreen
	BgYellow
	BgBlue
	BgMagenta
	BgCyan
	BgWhite
)

// Background Hi-Intensity text colors
const (
	BgHiBlack Attribute = iota + 100
	BgHiRed
	BgHiGreen
	BgHiYellow
	BgHiBlue
	BgHiMagenta
	BgHiCyan
	BgHiWhite
)

// New returns a newly created color object.
func New(value ...Attribute) *Color {
	c := &Color{params: make([]Attribute, 0)}
	c.Add(value...)
	return c
}

// Set sets the given parameters immediately. It will change the color of
// output with the given SGR parameters until color.Unset() is called.
func Set(p ...Attribute) *Color {
	c := New(p...)
	c.Set()
	return c
}

// Unset resets all escape attributes and clears the output. Usually should
// be called after Set().
func Unset() {
	if NoColor {
		return
	}

	fmt.Fprintf(Output, "%s[%dm", escape, Reset)
}

// Set sets the SGR sequence.
func (c *Color) Set() *Color {
	if c.isNoColorSet() {
		return c
	}

	fmt.Fprintf(Output, c.format())
	return c
}

func (c *Color) unset() {
	if c.isNoColorSet() {
		return
	}

	Unset()
}

// Add is used to chain SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
func (c *Color) Add(value ...Attribute) *Color {
	c.params = append(c.params, value...)
	return c
}

func (c *Color) prepend(value Attribute) {
	c.params = append(c.params, 0)
	copy(c.params[1:], c.params[0:])
	c.params[0] = value
}

// Output defines the standard output of the print functions. By default
// os.Stdout is used.
var Output = colorable.NewColorableStdout()

// Print formats using the default formats for its operands and writes to
// standard output. Spaces are added between operands when neither is a
// string. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Print(a ...interface{}) (n int, err error) {
	c.Set()
	defer c.unset()

	return fmt.Fprint(Output, a...)
}

// Printf formats according to a format specifier and writes to standard output.
// It returns the number of bytes written and any write error encountered.
// This is the standard fmt.Printf() method wrapped with the given color.
func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
	c.Set()
	defer c.unset()

	return fmt.Fprintf(Output, format, a...)
}

// Println formats using the default formats for its operands and writes to
// standard output. Spaces are always added between operands and a newline is
// appended. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Println(a ...interface{}) (n int, err error) {
	c.Set()
	defer c.unset()

	return fmt.Fprintln(Output, a...)
}

// PrintFunc returns a new function that prints the passed arguments as
// colorized with color.Print().
func (c *Color) PrintFunc() func(a ...interface{}) {
	return func(a ...interface{}) { c.Print(a...) }
}

// PrintfFunc returns a new function that prints the passed arguments as
// colorized with color.Printf().
func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
	return func(format string, a ...interface{}) { c.Printf(format, a...) }
}

// PrintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Println().
func (c *Color) PrintlnFunc() func(a ...interface{}) {
	return func(a ...interface{}) { c.Println(a...) }
}

// SprintFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprint(). Useful to put into or mix into other
// string. Windows users should use this in conjuction with color.Output, example:
//
//	put := New(FgYellow).SprintFunc()
//	fmt.Fprintf(color.Output, "This is a %s", put("warning"))
func (c *Color) SprintFunc() func(a ...interface{}) string {
	return func(a ...interface{}) string {
		return c.wrap(fmt.Sprint(a...))
	}
}

// SprintfFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintf(). Useful to put into or mix into other
// string. Windows users should use this in conjuction with color.Output.
func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
	return func(format string, a ...interface{}) string {
		return c.wrap(fmt.Sprintf(format, a...))
	}
}

// SprintlnFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintln(). Useful to put into or mix into other
// string. Windows users should use this in conjuction with color.Output.
func (c *Color) SprintlnFunc() func(a ...interface{}) string {
	return func(a ...interface{}) string {
		return c.wrap(fmt.Sprintln(a...))
	}
}

// sequence returns a formated SGR sequence to be plugged into a "\x1b[...m"
// an example output might be: "1;36" -> bold cyan
func (c *Color) sequence() string {
	format := make([]string, len(c.params))
	for i, v := range c.params {
		format[i] = strconv.Itoa(int(v))
	}

	return strings.Join(format, ";")
}

// wrap wraps the s string with the colors attributes. The string is ready to
// be printed.
func (c *Color) wrap(s string) string {
	if c.isNoColorSet() {
		return s
	}

	return c.format() + s + c.unformat()
}

func (c *Color) format() string {
	return fmt.Sprintf("%s[%sm", escape, c.sequence())
}

func (c *Color) unformat() string {
	return fmt.Sprintf("%s[%dm", escape, Reset)
}

// DisableColor disables the color output. Useful to not change any existing
// code and still being able to output. Can be used for flags like
// "--no-color". To enable back use EnableColor() method.
func (c *Color) DisableColor() {
	c.noColor = boolPtr(true)
}

// EnableColor enables the color output. Use it in conjuction with
// DisableColor(). Otherwise this method has no side effects.
func (c *Color) EnableColor() {
	c.noColor = boolPtr(false)
}

func (c *Color) isNoColorSet() bool {
	// check first if we have user setted action
	if c.noColor != nil {
		return *c.noColor
	}

	// if not return the global option, which is disabled by default
	return NoColor
}

// Equals returns a boolean value indicating whether two colors are equal.
func (c *Color) Equals(c2 *Color) bool {
	if len(c.params) != len(c2.params) {
		return false
	}

	for _, attr := range c.params {
		if !c2.attrExists(attr) {
			return false
		}
	}

	return true
}

func (c *Color) attrExists(a Attribute) bool {
	for _, attr := range c.params {
		if attr == a {
			return true
		}
	}

	return false
}

func boolPtr(v bool) *bool {
	return &v
}

// colorsCache is used to reduce the count of created Color objects and
// allows to reuse already created objects with required Attribute.
var colorsCache = make(map[Attribute]*Color)

var colorsCacheMu = new(sync.Mutex) // protects colorsCache

func getCachedColor(p Attribute) *Color {
	colorsCacheMu.Lock()
	defer colorsCacheMu.Unlock()

	c, ok := colorsCache[p]
	if !ok {
		c = New(p)
		colorsCache[p] = c
	}

	return c
}

func printColor(format string, p Attribute, a ...interface{}) {
	c := getCachedColor(p)

	if !strings.HasSuffix(format, "\n") {
		format += "\n"
	}

	if len(a) == 0 {
		c.Print(format)
		return
	}

	c.Printf(format, a...)
}

func printString(format string, p Attribute, a ...interface{}) string {
	c := getCachedColor(p)

	if len(a) == 0 {
		return c.SprintFunc()(format)
	}

	return c.SprintfFunc()(format, a...)
}

// Black is an convenient helper function to print with black foreground. A
// newline is appended to format by default.
func Black(format string, a ...interface{}) { printColor(format, FgBlack, a...) }

// Red is an convenient helper function to print with red foreground. A
// newline is appended to format by default.
func Red(format string, a ...interface{}) { printColor(format, FgRed, a...) }

// Green is an convenient helper function to print with green foreground. A
// newline is appended to format by default.
func Green(format string, a ...interface{}) { printColor(format, FgGreen, a...) }

// Yellow is an convenient helper function to print with yellow foreground.
// A newline is appended to format by default.
func Yellow(format string, a ...interface{}) { printColor(format, FgYellow, a...) }

// Blue is an convenient helper function to print with blue foreground. A
// newline is appended to format by default.
func Blue(format string, a ...interface{}) { printColor(format, FgBlue, a...) }

// Magenta is an convenient helper function to print with magenta foreground.
// A newline is appended to format by default.
func Magenta(format string, a ...interface{}) { printColor(format, FgMagenta, a...) }

// Cyan is an convenient helper function to print with cyan foreground. A
// newline is appended to format by default.
func Cyan(format string, a ...interface{}) { printColor(format, FgCyan, a...) }

// White is an convenient helper function to print with white foreground. A
// newline is appended to format by default.
func White(format string, a ...interface{}) { printColor(format, FgWhite, a...) }

// BlackString is an convenient helper function to return a string with black
// foreground.
func BlackString(format string, a ...interface{}) string { return printString(format, FgBlack, a...) }

// RedString is an convenient helper function to return a string with red
// foreground.
func RedString(format string, a ...interface{}) string { return printString(format, FgRed, a...) }

// GreenString is an convenient helper function to return a string with green
// foreground.
func GreenString(format string, a ...interface{}) string { return printString(format, FgGreen, a...) }

// YellowString is an convenient helper function to return a string with yellow
// foreground.
func YellowString(format string, a ...interface{}) string { return printString(format, FgYellow, a...) }

// BlueString is an convenient helper function to return a string with blue
// foreground.
func BlueString(format string, a ...interface{}) string { return printString(format, FgBlue, a...) }

// MagentaString is an convenient helper function to return a string with magenta
// foreground.
func MagentaString(format string, a ...interface{}) string {
	return printString(format, FgMagenta, a...)
}

// CyanString is an convenient helper function to return a string with cyan
// foreground.
func CyanString(format string, a ...interface{}) string { return printString(format, FgCyan, a...) }

// WhiteString is an convenient helper function to return a string with white
// foreground.
func WhiteString(format string, a ...interface{}) string { return printString(format, FgWhite, a...) }
<commit_msg>Rename printColor and printString to colorPrint and colorString<commit_after>package color

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"sync"

	"github.com/mattn/go-colorable"
	"github.com/mattn/go-isatty"
)

// NoColor defines if the output is colorized or not. It's dynamically set to
// false or true based on the stdout's file descriptor referring to a terminal
// or not. This is a global option and affects all colors. For more control
// over each color block use the methods DisableColor() individually.
var NoColor = !isatty.IsTerminal(os.Stdout.Fd())

// Color defines a custom color object which is defined by SGR parameters.
type Color struct {
	params  []Attribute
	noColor *bool
}

// Attribute defines a single SGR Code
type Attribute int

const escape = "\x1b"

// Base attributes
const (
	Reset Attribute = iota
	Bold
	Faint
	Italic
	Underline
	BlinkSlow
	BlinkRapid
	ReverseVideo
	Concealed
	CrossedOut
)

// Foreground text colors
const (
	FgBlack Attribute = iota + 30
	FgRed
	FgGreen
	FgYellow
	FgBlue
	FgMagenta
	FgCyan
	FgWhite
)

// Foreground Hi-Intensity text colors
const (
	FgHiBlack Attribute = iota + 90
	FgHiRed
	FgHiGreen
	FgHiYellow
	FgHiBlue
	FgHiMagenta
	FgHiCyan
	FgHiWhite
)

// Background text colors
const (
	BgBlack Attribute = iota + 40
	BgRed
	BgGreen
	BgYellow
	BgBlue
	BgMagenta
	BgCyan
	BgWhite
)

// Background Hi-Intensity text colors
const (
	BgHiBlack Attribute = iota + 100
	BgHiRed
	BgHiGreen
	BgHiYellow
	BgHiBlue
	BgHiMagenta
	BgHiCyan
	BgHiWhite
)

// New returns a newly created color object.
func New(value ...Attribute) *Color {
	c := &Color{params: make([]Attribute, 0)}
	c.Add(value...)
	return c
}

// Set sets the given parameters immediately. It will change the color of
// output with the given SGR parameters until color.Unset() is called.
func Set(p ...Attribute) *Color {
	c := New(p...)
	c.Set()
	return c
}

// Unset resets all escape attributes and clears the output. Usually should
// be called after Set().
func Unset() {
	if NoColor {
		return
	}

	fmt.Fprintf(Output, "%s[%dm", escape, Reset)
}

// Set sets the SGR sequence.
func (c *Color) Set() *Color {
	if c.isNoColorSet() {
		return c
	}

	fmt.Fprintf(Output, c.format())
	return c
}

func (c *Color) unset() {
	if c.isNoColorSet() {
		return
	}

	Unset()
}

// Add is used to chain SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
func (c *Color) Add(value ...Attribute) *Color {
	c.params = append(c.params, value...)
	return c
}

func (c *Color) prepend(value Attribute) {
	c.params = append(c.params, 0)
	copy(c.params[1:], c.params[0:])
	c.params[0] = value
}

// Output defines the standard output of the print functions. By default
// os.Stdout is used.
var Output = colorable.NewColorableStdout()

// Print formats using the default formats for its operands and writes to
// standard output. Spaces are added between operands when neither is a
// string. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Print(a ...interface{}) (n int, err error) {
	c.Set()
	defer c.unset()

	return fmt.Fprint(Output, a...)
}

// Printf formats according to a format specifier and writes to standard output.
// It returns the number of bytes written and any write error encountered.
// This is the standard fmt.Printf() method wrapped with the given color.
func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
	c.Set()
	defer c.unset()

	return fmt.Fprintf(Output, format, a...)
}

// Println formats using the default formats for its operands and writes to
// standard output. Spaces are always added between operands and a newline is
// appended. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Println(a ...interface{}) (n int, err error) {
	c.Set()
	defer c.unset()

	return fmt.Fprintln(Output, a...)
}

// PrintFunc returns a new function that prints the passed arguments as
// colorized with color.Print().
func (c *Color) PrintFunc() func(a ...interface{}) {
	return func(a ...interface{}) { c.Print(a...) }
}

// PrintfFunc returns a new function that prints the passed arguments as
// colorized with color.Printf().
func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
	return func(format string, a ...interface{}) { c.Printf(format, a...) }
}

// PrintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Println().
func (c *Color) PrintlnFunc() func(a ...interface{}) {
	return func(a ...interface{}) { c.Println(a...) }
}

// SprintFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprint(). Useful to put into or mix into other
// string. Windows users should use this in conjuction with color.Output, example:
//
//	put := New(FgYellow).SprintFunc()
//	fmt.Fprintf(color.Output, "This is a %s", put("warning"))
func (c *Color) SprintFunc() func(a ...interface{}) string {
	return func(a ...interface{}) string {
		return c.wrap(fmt.Sprint(a...))
	}
}

// SprintfFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintf(). Useful to put into or mix into other
// string. Windows users should use this in conjuction with color.Output.
func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
	return func(format string, a ...interface{}) string {
		return c.wrap(fmt.Sprintf(format, a...))
	}
}

// SprintlnFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintln(). Useful to put into or mix into other
// string. Windows users should use this in conjuction with color.Output.
func (c *Color) SprintlnFunc() func(a ...interface{}) string {
	return func(a ...interface{}) string {
		return c.wrap(fmt.Sprintln(a...))
	}
}

// sequence returns a formated SGR sequence to be plugged into a "\x1b[...m"
// an example output might be: "1;36" -> bold cyan
func (c *Color) sequence() string {
	format := make([]string, len(c.params))
	for i, v := range c.params {
		format[i] = strconv.Itoa(int(v))
	}

	return strings.Join(format, ";")
}

// wrap wraps the s string with the colors attributes. The string is ready to
// be printed.
func (c *Color) wrap(s string) string {
	if c.isNoColorSet() {
		return s
	}

	return c.format() + s + c.unformat()
}

func (c *Color) format() string {
	return fmt.Sprintf("%s[%sm", escape, c.sequence())
}

func (c *Color) unformat() string {
	return fmt.Sprintf("%s[%dm", escape, Reset)
}

// DisableColor disables the color output. Useful to not change any existing
// code and still being able to output. Can be used for flags like
// "--no-color". To enable back use EnableColor() method.
func (c *Color) DisableColor() {
	c.noColor = boolPtr(true)
}

// EnableColor enables the color output. Use it in conjuction with
// DisableColor(). Otherwise this method has no side effects.
func (c *Color) EnableColor() {
	c.noColor = boolPtr(false)
}

func (c *Color) isNoColorSet() bool {
	// check first if we have user setted action
	if c.noColor != nil {
		return *c.noColor
	}

	// if not return the global option, which is disabled by default
	return NoColor
}

// Equals returns a boolean value indicating whether two colors are equal.
func (c *Color) Equals(c2 *Color) bool {
	if len(c.params) != len(c2.params) {
		return false
	}

	for _, attr := range c.params {
		if !c2.attrExists(attr) {
			return false
		}
	}

	return true
}

func (c *Color) attrExists(a Attribute) bool {
	for _, attr := range c.params {
		if attr == a {
			return true
		}
	}

	return false
}

func boolPtr(v bool) *bool {
	return &v
}

// colorsCache is used to reduce the count of created Color objects and
// allows to reuse already created objects with required Attribute.
var colorsCache = make(map[Attribute]*Color)

var colorsCacheMu = new(sync.Mutex) // protects colorsCache

func getCachedColor(p Attribute) *Color {
	colorsCacheMu.Lock()
	defer colorsCacheMu.Unlock()

	c, ok := colorsCache[p]
	if !ok {
		c = New(p)
		colorsCache[p] = c
	}

	return c
}

func colorPrint(format string, p Attribute, a ...interface{}) {
	c := getCachedColor(p)

	if !strings.HasSuffix(format, "\n") {
		format += "\n"
	}

	if len(a) == 0 {
		c.Print(format)
	} else {
		c.Printf(format, a...)
	}
}

func colorString(format string, p Attribute, a ...interface{}) string {
	c := getCachedColor(p)

	if len(a) == 0 {
		return c.SprintFunc()(format)
	}

	return c.SprintfFunc()(format, a...)
}

// Black is an convenient helper function to print with black foreground. A
// newline is appended to format by default.
func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) }

// Red is an convenient helper function to print with red foreground. A
// newline is appended to format by default.
func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) }

// Green is an convenient helper function to print with green foreground. A
// newline is appended to format by default.
func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) }

// Yellow is an convenient helper function to print with yellow foreground.
// A newline is appended to format by default.
func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) }

// Blue is an convenient helper function to print with blue foreground. A
// newline is appended to format by default.
func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) }

// Magenta is an convenient helper function to print with magenta foreground.
// A newline is appended to format by default.
func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) }

// Cyan is an convenient helper function to print with cyan foreground. A
// newline is appended to format by default.
func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) }

// White is an convenient helper function to print with white foreground. A
// newline is appended to format by default.
func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) }

// BlackString is an convenient helper function to return a string with black
// foreground.
func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) }

// RedString is an convenient helper function to return a string with red
// foreground.
func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) }

// GreenString is an convenient helper function to return a string with green
// foreground.
func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) }

// YellowString is an convenient helper function to return a string with yellow
// foreground.
func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) }

// BlueString is an convenient helper function to return a string with blue
// foreground.
func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) }

// MagentaString is an convenient helper function to return a string with magenta
// foreground.
func MagentaString(format string, a ...interface{}) string {
	return colorString(format, FgMagenta, a...)
}

// CyanString is an convenient helper function to return a string with cyan
// foreground.
func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) }

// WhiteString is an convenient helper function to return a string with white
// foreground.
func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) }
<|endoftext|>