<commit_before>package api

import (
	"github.com/fritzpay/paymentd/pkg/service"
	"github.com/fritzpay/paymentd/pkg/service/api/v1"
	"gopkg.in/inconshreveable/log15.v2"
	"net/http"
)

// Handler is the (HTTP) API Handler
type Handler struct {
	ctx *service.Context
	log log15.Logger

	mux *http.ServeMux
}

// NewHandler creates a new API Handler
func NewHandler(ctx *service.Context) (*Handler, error) {
	h := &Handler{
		ctx: ctx,
		log: ctx.Log().New(log15.Ctx{
			"pkg": "github.com/fritzpay/paymentd/pkg/service/api",
		}),

		mux: http.NewServeMux(),
	}

	h.log.Info("registering API service v1...")
	v1.NewService(h.ctx, h.mux)

	return h, nil
}

// ServeHTTP implements the http.Handler
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer func() {
		if err := recover(); err != nil {
			h.log.Crit("panic on serving HTTP", log15.Ctx{"panic": err})
		}
	}()
	service.SetRequestContext(r, h.ctx)
	defer service.ClearRequestContext(r)
	h.mux.ServeHTTP(w, r)
}
<commit_msg>assign service v1 default logger<commit_after>package api

import (
	"github.com/fritzpay/paymentd/pkg/service"
	"github.com/fritzpay/paymentd/pkg/service/api/v1"
	"gopkg.in/inconshreveable/log15.v2"
	"net/http"
)

// Handler is the (HTTP) API Handler
type Handler struct {
	ctx *service.Context
	log log15.Logger

	mux *http.ServeMux
}

// NewHandler creates a new API Handler
func NewHandler(ctx *service.Context) (*Handler, error) {
	h := &Handler{
		ctx: ctx,
		log: ctx.Log().New(log15.Ctx{
			"pkg": "github.com/fritzpay/paymentd/pkg/service/api",
		}),

		mux: http.NewServeMux(),
	}

	h.log.Info("registering API service v1...")
	v1.NewService(h.ctx, h.mux)
	v1.Log = h.log.New(log15.Ctx{
		"pkg": "github.com/fritzpay/paymentd/pkg/service/api/v1",
	})

	return h, nil
}

// ServeHTTP implements the http.Handler
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer func() {
		if err := recover(); err != nil {
			h.log.Crit("panic on serving HTTP", log15.Ctx{"panic": err})
		}
	}()
	service.SetRequestContext(r, h.ctx)
	defer service.ClearRequestContext(r)
	h.mux.ServeHTTP(w, r)
}
<|endoftext|>


<commit_before>package snmpquery

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

type Query struct {
	Id          int
	Query       string
	Destination string
	Response    string
	Error       int
}

func HandleQuery(query *Query) {
	time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
	query.Response = "whatever " + strconv.Itoa(rand.Intn(1e3))
}

func ProcessQueriesFromChannel(input chan Query, processed chan Query) {
	for query := range input {
		fmt.Println("Begin processing", query)
		HandleQuery(&query)
		fmt.Println("Processed", query)
		processed <- query
	}
}

func Process(input chan Query, processed chan Query) {
	m := make(map[string]chan Query)

	for query := range input {
		fmt.Println("EFA processing query ", query.Destination, query)

		channel, exists := m[query.Destination]
		if exists == false {
			channel := make(chan Query, 10)
			m[query.Destination] = channel
			fmt.Println("EFA creating a go routine for ", query.Destination)
			go ProcessQueriesFromChannel(channel, processed)
		}
		channel <- query

	}
}
<commit_msg>Fixed minor errors. Added panic.<commit_after>package snmpquery

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

type Query struct {
	Id          int
	Query       string
	Destination string
	Response    string
	Error       int
}

func HandleQuery(query *Query) {
	time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
	query.Response = "whatever " + strconv.Itoa(rand.Intn(1e3))
}

func ProcessQueriesFromChannel(input chan Query, processed chan Query) {
	fmt.Println("Process queries from channel", input)
	for query := range input {
		fmt.Println("Begin processing", query)
		HandleQuery(&query)
		fmt.Println("Processed", query)
		processed <- query
	}
}

func Process(input chan Query, processed chan Query) {
	m := make(map[string]chan Query)

	for query := range input {
		fmt.Println("EFA processing query ", query.Destination, query)

		_, exists := m[query.Destination]
		if exists == false {
			channel_tmp := make(chan Query, 10)
			m[query.Destination] = channel_tmp
			fmt.Println("EFA creating a go routine for ", query.Destination, channel_tmp)
			go ProcessQueriesFromChannel(channel_tmp, processed)
		}

		if len(m) > 10 {
			panic(fmt.Sprintf("Hay más de 10 hilos, ¿qué pasa?"))
		}

		channel, _ := m[query.Destination]
		channel <- query

	}
}
<|endoftext|>


<commit_before>package redis

import (
	"sync"
	"time"
	"github.com/BluePecker/JwtAuth/pkg/storage"
	"github.com/go-redis/redis"
	"crypto/md5"
	"encoding/hex"
	"github.com/BluePecker/JwtAuth/pkg/storage/redis/uri"
	"reflect"
	"github.com/Sirupsen/logrus"
	"github.com/kataras/iris/core/errors"
)

type (
	Redis struct {
		create time.Time
		mu     sync.RWMutex
		engine Client
	}

	Client interface {
		Ping() *redis.StatusCmd

		Close() error

		Pipelined(fn func(redis.Pipeliner) error) ([]redis.Cmder, error)

		ZScore(key, field string) *redis.FloatCmd

		ZRem(key string, members ... interface{}) *redis.IntCmd

		ZRange(key string, start, stop int64) *redis.StringSliceCmd

		ZCard(key string) *redis.IntCmd

		Del(keys ... string) *redis.IntCmd

		ZRemRangeByRank(key string, start, stop int64) *redis.IntCmd
	}
)

func inject(from, target reflect.Value) {
	indirect := reflect.Indirect(target.Elem())
	for index := 0; index < from.Elem().NumField(); index++ {
		name := from.Elem().Type().Field(index).Name
		f1 := from.Elem().FieldByName(name)
		f2 := indirect.FieldByName(name)
		if f2.IsValid() {
			if f1.Type() == f2.Type() && f2.CanSet() {
				f2.Set(f1)
			}
		}
	}
}

func (r *Redis) Initializer(opts string) error {
	generic, err := uri.Parser(opts)
	if err != nil {
		return err
	}
	switch reflect.ValueOf(generic).Interface().(type) {
	case *redis.ClusterOptions:
		options := &redis.ClusterOptions{}
		inject(reflect.ValueOf(generic), reflect.ValueOf(options))
		r.engine = redis.NewClusterClient(options)
		break
	case *redis.Options:
		options := &redis.Options{}
		inject(reflect.ValueOf(generic), reflect.ValueOf(options))
		r.engine = redis.NewClient(options)
		break
	}
	statusCmd := r.engine.Ping()
	if statusCmd.Err() != nil {
		logrus.Error(statusCmd.Err())
		defer r.engine.Close()
	}
	return statusCmd.Err()
}

func (r *Redis) HSet(key, field string, value interface{}, maxLen, expire int64) error {
	r.mu.Lock()
	defer r.mu.Unlock()
	tmp := jwtMd5(key)
	val := jwtMd5(tmp + field)
	_, err := r.engine.Pipelined(func(p redis.Pipeliner) error {
		exp := time.Duration(expire) * time.Second
		score := expire + int64(time.Now().Unix())
		if cmd := p.ZAdd(tmp, redis.Z{Score: float64(score), Member: val}); cmd.Err() != nil {
			return cmd.Err()
		} else {
			if cmd := p.Expire(tmp, exp); cmd.Err() != nil {
				return cmd.Err()
			}
			if cmd := p.Set(val, value, exp); cmd.Err() != nil {
				p.ZRem(tmp, redis.Z{Score: float64(score), Member: val})
				return cmd.Err()
			}
		}
		return nil
	})
	if err != nil {
		return err
	} else {
		if cmd := r.engine.ZCard(tmp); cmd.Err() != nil {
			return cmd.Err()
		} else {
			logrus.Error(tmp, " ", cmd.Val(), " ", maxLen)
			if cmd.Val() > maxLen {
				if cmd := r.engine.ZRange(tmp, 0, cmd.Val()-maxLen-1); cmd.Err() != nil {
					return cmd.Err()
				} else {
					r.engine.Del(cmd.Val()...)
				}
				cmd = r.engine.ZRemRangeByRank(tmp, 0, cmd.Val()-maxLen-1)
				if cmd.Err() != nil {
					return cmd.Err()
				}
			}
			return nil
		}
	}
}

func (r *Redis) HGet(key, field string) (string, float64, error) {
	tmp := jwtMd5(key)
	return r.hGet(tmp, jwtMd5(tmp+field))
}

func (r *Redis) hGet(key, field string) (string, float64, error) {
	if cmd := r.engine.ZScore(key, field); cmd.Err() != nil {
		return "", -1, cmd.Err()
	} else if cmd.Val() < float64(time.Now().Unix()) {
		if cmd := r.engine.ZRem(key, field); cmd.Err() != nil {
			return "", -1, cmd.Err()
		} else {
			return "", -1, errors.New("key has been expired.")
		}
	} else {
		var strCmd *redis.StringCmd
		var durCmd *redis.DurationCmd
		_, err := r.engine.Pipelined(func(p redis.Pipeliner) error {
			if strCmd = p.Get(field); cmd.Err() != nil {
				return strCmd.Err()
			}
			if durCmd = p.TTL(field); cmd.Err() != nil {
				return durCmd.Err()
			}
			return nil
		})
		if err != nil {
			return "", -1, err
		}
		return strCmd.Val(), durCmd.Val().Seconds(), nil
	}
}

func (r *Redis) HScan(key string, do func(token string, ttl float64)) error {
	tmp := jwtMd5(key)
	if cmd := r.engine.ZRange(tmp, 0, -1); cmd.Err() != nil {
		return cmd.Err()
	} else {
		for _, field := range cmd.Val() {
			singed, ttl, err := r.hGet(tmp, field)
			if err == nil {
				do(singed, ttl)
			} else {
				logrus.Info(err)
			}
		}
		return nil
	}
}

func (r *Redis) HRem(key string, field ... string) error {
	var v1 []interface{}
	var v2 []string
	tmp := jwtMd5(key)
	for _, v := range field {
		v1 = append(v1, jwtMd5(tmp+v))
		v2 = append(v2, jwtMd5(tmp+v))
	}
	_, err := r.engine.Pipelined(func(p redis.Pipeliner) error {
		p.ZRem(tmp, v1...)
		p.Del(v2...)
		return nil
	})
	return err
}

func jwtMd5(key string) string {
	hash := md5.New()
	hash.Write([]byte(key))
	return hex.EncodeToString(hash.Sum([]byte("jwt#")))
}

func init() {
	storage.Register("redis", &Redis{})
}
<commit_msg>debug<commit_after>package redis

import (
	"sync"
	"time"
	"github.com/BluePecker/JwtAuth/pkg/storage"
	"github.com/go-redis/redis"
	"crypto/md5"
	"encoding/hex"
	"github.com/BluePecker/JwtAuth/pkg/storage/redis/uri"
	"reflect"
	"github.com/Sirupsen/logrus"
	"github.com/kataras/iris/core/errors"
)

type (
	Redis struct {
		create time.Time
		mu     sync.RWMutex
		engine Client
	}

	Client interface {
		Ping() *redis.StatusCmd

		Close() error

		Pipelined(fn func(redis.Pipeliner) error) ([]redis.Cmder, error)

		ZScore(key, field string) *redis.FloatCmd

		ZRem(key string, members ... interface{}) *redis.IntCmd

		ZRange(key string, start, stop int64) *redis.StringSliceCmd

		ZCard(key string) *redis.IntCmd

		Del(keys ... string) *redis.IntCmd

		ZRemRangeByRank(key string, start, stop int64) *redis.IntCmd
	}
)

func inject(from, target reflect.Value) {
	indirect := reflect.Indirect(target.Elem())
	for index := 0; index < from.Elem().NumField(); index++ {
		name := from.Elem().Type().Field(index).Name
		f1 := from.Elem().FieldByName(name)
		f2 := indirect.FieldByName(name)
		if f2.IsValid() {
			if f1.Type() == f2.Type() && f2.CanSet() {
				f2.Set(f1)
			}
		}
	}
}

func (r *Redis) Initializer(opts string) error {
	generic, err := uri.Parser(opts)
	if err != nil {
		return err
	}
	switch reflect.ValueOf(generic).Interface().(type) {
	case *redis.ClusterOptions:
		options := &redis.ClusterOptions{}
		inject(reflect.ValueOf(generic), reflect.ValueOf(options))
		r.engine = redis.NewClusterClient(options)
		break
	case *redis.Options:
		options := &redis.Options{}
		inject(reflect.ValueOf(generic), reflect.ValueOf(options))
		r.engine = redis.NewClient(options)
		break
	}
	statusCmd := r.engine.Ping()
	if statusCmd.Err() != nil {
		logrus.Error(statusCmd.Err())
		defer r.engine.Close()
	}
	return statusCmd.Err()
}

func (r *Redis) HSet(key, field string, value interface{}, maxLen, expire int64) error {
	r.mu.Lock()
	defer r.mu.Unlock()
	tmp := jwtMd5(key)
	val := jwtMd5(tmp + field)
	_, err := r.engine.Pipelined(func(p redis.Pipeliner) error {
		exp := time.Duration(expire) * time.Second
		score := expire + int64(time.Now().Unix())
		if cmd := p.ZAdd(tmp, redis.Z{Score: float64(score), Member: val}); cmd.Err() != nil {
			return cmd.Err()
		} else {
			if cmd := p.Expire(tmp, exp); cmd.Err() != nil {
				return cmd.Err()
			}
			if cmd := p.Set(val, value, exp); cmd.Err() != nil {
				p.ZRem(tmp, redis.Z{Score: float64(score), Member: val})
				return cmd.Err()
			}
		}
		return nil
	})
	go func() {
		if err == nil {
			if cmd := r.engine.ZCard(tmp); cmd.Err() != nil {
				logrus.Error(cmd.Err())
			} else {
				// todo remove debug info
				logrus.Error(tmp, " ", cmd.Val(), " ", maxLen)
				if cmd.Val() > maxLen {
					if cmd := r.engine.ZRange(tmp, 0, cmd.Val()-maxLen-1); cmd.Err() != nil {
						logrus.Error(cmd.Err())
					} else {
						r.engine.Del(cmd.Val()...)
					}
					cmd = r.engine.ZRemRangeByRank(tmp, 0, cmd.Val()-maxLen-1)
					if cmd.Err() != nil {
						logrus.Error(cmd.Err())
					}
				}
			}
		}
	}()
	return nil
}

func (r *Redis) HGet(key, field string) (string, float64, error) {
	tmp := jwtMd5(key)
	return r.hGet(tmp, jwtMd5(tmp+field))
}

func (r *Redis) hGet(key, field string) (string, float64, error) {
	if cmd := r.engine.ZScore(key, field); cmd.Err() != nil {
		return "", -1, cmd.Err()
	} else if cmd.Val() < float64(time.Now().Unix()) {
		if cmd := r.engine.ZRem(key, field); cmd.Err() != nil {
			return "", -1, cmd.Err()
		} else {
			return "", -1, errors.New("key has been expired.")
		}
	} else {
		var strCmd *redis.StringCmd
		var durCmd *redis.DurationCmd
		_, err := r.engine.Pipelined(func(p redis.Pipeliner) error {
			if strCmd = p.Get(field); cmd.Err() != nil {
				return strCmd.Err()
			}
			if durCmd = p.TTL(field); cmd.Err() != nil {
				return durCmd.Err()
			}
			return nil
		})
		if err != nil {
			return "", -1, err
		}
		return strCmd.Val(), durCmd.Val().Seconds(), nil
	}
}

func (r *Redis) HScan(key string, do func(token string, ttl float64)) error {
	tmp := jwtMd5(key)
	if cmd := r.engine.ZRange(tmp, 0, -1); cmd.Err() != nil {
		return cmd.Err()
	} else {
		for _, field := range cmd.Val() {
			singed, ttl, err := r.hGet(tmp, field)
			if err == nil {
				do(singed, ttl)
			} else {
				logrus.Info(err)
			}
		}
		return nil
	}
}

func (r *Redis) HRem(key string, field ... string) error {
	var v1 []interface{}
	var v2 []string
	tmp := jwtMd5(key)
	for _, v := range field {
		v1 = append(v1, jwtMd5(tmp+v))
		v2 = append(v2, jwtMd5(tmp+v))
	}
	_, err := r.engine.Pipelined(func(p redis.Pipeliner) error {
		p.ZRem(tmp, v1...)
		p.Del(v2...)
		return nil
	})
	return err
}

func jwtMd5(key string) string {
	hash := md5.New()
	hash.Write([]byte(key))
	return hex.EncodeToString(hash.Sum([]byte("jwt#")))
}

func init() {
	storage.Register("redis", &Redis{})
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
	"log"
	"net/http"
)

type RepoStruct struct {
	Name *string
	Protected bool
}

// GetAllRepos will return a list of repos for a Github Organization
func getAllRepos(orgname string) []RepoStruct {
	client := getClient()

	opt := &github.RepositoryListByOrgOptions{
		ListOptions: github.ListOptions{PerPage: 100},
	}
	// get all pages of results
	var allRepos []github.Repository
	for {
		repos, resp, err := client.Repositories.ListByOrg(orgname, opt)
		if err != nil {
			return nil
		}
		allRepos = append(allRepos, repos...)
		if resp.NextPage == 0 {
			break
		}
		opt.ListOptions.Page = resp.NextPage
	}
	log.Printf("Found %d repo(s) for the organization %s", len(allRepos), orgname)

	var repos []RepoStruct
	repos = make([]RepoStruct, len(allRepos))
	for i, repo := range allRepos {
		rs := RepoStruct{}
		rs.Name = repo.Name

		//TODO: Make call to Github api with beta header and get the value of protected
		rs.Protected = getProtectedStatus(repo)

		repos[i] = rs
	}
	return repos
}

func getProtectedStatus(github.Repository) bool {
	return false
}

func getClient() *github.Client {
	var tc *http.Client
	envToken := *_config.githubkey
	if len(envToken) > 0 {
		token := oauth2.Token{AccessToken: envToken}
		ts := oauth2.StaticTokenSource(&token)
		tc = oauth2.NewClient(oauth2.NoContext, ts)
	}
	client := github.NewClient(tc)
	return client
}<commit_msg>Test travis build<commit_after>package main

import (
	"github.com/google/go-github/github"
	"golang.org/x/oauth2"
	"log"
	"net/http"
)

type RepoStruct struct {
	Name *string
	Protected bool
}

// GetAllRepos will return a list of repos for a Github Organization
func getAllRepos(orgname string) []RepoStruct {
	client := getClient()

	opt := &github.RepositoryListByOrgOptions{
		ListOptions: github.ListOptions{PerPage: 100},
	}
	// get all pages of results
	var allRepos []github.Repository
	for {
		repos, resp, err := client.Repositories.ListByOrg(orgname, opt)
		if err != nil {
			return nil
		}
		allRepos = append(allRepos, repos...)
		if resp.NextPage == 0 {
			break
		}
		opt.ListOptions.Page = resp.NextPage
	}
	log.Printf("Found %d repo(s) for the organization %s", len(allRepos), orgname)

	var repos []RepoStruct
	repos = make([]RepoStruct, len(allRepos))
	for i, repo := range allRepos {
		rs := RepoStruct{}
		rs.Name = repo.Name

		//TODO: Make call to Github api with beta header and get the value of protected
		rs.Protected = getProtectedStatus(repo)

		repos[i] = rs
	}
	return repos
}

func getProtectedStatus(github.Repository) bool {
	// TODO
	return false
}

func getClient() *github.Client {
	var tc *http.Client
	envToken := *_config.githubkey
	if len(envToken) > 0 {
		token := oauth2.Token{AccessToken: envToken}
		ts := oauth2.StaticTokenSource(&token)
		tc = oauth2.NewClient(oauth2.NoContext, ts)
	}
	client := github.NewClient(tc)
	return client
}<|endoftext|>


<commit_before>// +build windows

package process

import (
	"errors"
	"fmt"
	"strings"
	"syscall"
	"time"
	"unsafe"

	"github.com/StackExchange/wmi"
	"github.com/shirou/w32"

	cpu "github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/internal/common"
	net "github.com/shirou/gopsutil/net"
)

const (
	NoMoreFiles   = 0x12
	MaxPathLength = 260
)

var (
	modpsapi                 = syscall.NewLazyDLL("psapi.dll")
	procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
)

type SystemProcessInformation struct {
	NextEntryOffset   uint64
	NumberOfThreads   uint64
	Reserved1         [48]byte
	Reserved2         [3]byte
	UniqueProcessID   uintptr
	Reserved3         uintptr
	HandleCount       uint64
	Reserved4         [4]byte
	Reserved5         [11]byte
	PeakPagefileUsage uint64
	PrivatePageCount  uint64
	Reserved6         [6]uint64
}

// Memory_info_ex is different between OSes
type MemoryInfoExStat struct {
}

type MemoryMapsStat struct {
}

type Win32_Process struct {
	Name                string
	ExecutablePath      *string
	CommandLine         *string
	Priority            uint32
	CreationDate        *time.Time
	ProcessID           uint32
	ThreadCount         uint32
	Status              *string
	ReadOperationCount  uint64
	ReadTransferCount   uint64
	WriteOperationCount uint64
	WriteTransferCount  uint64

	/*
		CSCreationClassName   string
		CSName                string
		Caption               *string
		CreationClassName     string
		Description           *string
		ExecutionState        *uint16
		HandleCount           uint32
		KernelModeTime        uint64
		MaximumWorkingSetSize *uint32
		MinimumWorkingSetSize *uint32
		OSCreationClassName   string
		OSName                string
		OtherOperationCount   uint64
		OtherTransferCount    uint64
		PageFaults            uint32
		PageFileUsage         uint32
		ParentProcessID       uint32
		PeakPageFileUsage     uint32
		PeakVirtualSize       uint64
		PeakWorkingSetSize    uint32
		PrivatePageCount      uint64
		TerminationDate       *time.Time
		UserModeTime          uint64
		WorkingSetSize        uint64
	*/
}

func Pids() ([]int32, error) {
	var ret []int32

	procs, err := processes()
	if err != nil {
		return ret, nil
	}

	for _, proc := range procs {
		ret = append(ret, proc.Pid)
	}

	return ret, nil
}

func (p *Process) Ppid() (int32, error) {
	ret, _, _, err := p.getFromSnapProcess(p.Pid)
	if err != nil {
		return 0, err
	}
	return ret, nil
}

func GetWin32Proc(pid int32) ([]Win32_Process, error) {
	var dst []Win32_Process
	query := fmt.Sprintf("WHERE ProcessId = %d", pid)
	q := wmi.CreateQuery(&dst, query)
	err := wmi.Query(q, &dst)
	if err != nil {
		return []Win32_Process{}, fmt.Errorf("could not get win32Proc: %s", err)
	}
	if len(dst) != 1 {
		return []Win32_Process{}, fmt.Errorf("could not get win32Proc: empty")
	}
	return dst, nil
}

func (p *Process) Name() (string, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil {
		return "", fmt.Errorf("could not get Name: %s", err)
	}
	return dst[0].Name, nil
}
func (p *Process) Exe() (string, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil {
		return "", fmt.Errorf("could not get ExecutablePath: %s", err)
	}
	return *dst[0].ExecutablePath, nil
}
func (p *Process) Cmdline() (string, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil {
		return "", fmt.Errorf("could not get CommandLine: %s", err)
	}
	return *dst[0].CommandLine, nil
}

// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument. This merely returns the CommandLine informations passed
// to the process split on the 0x20 ASCII character.
func (p *Process) CmdlineSlice() ([]string, error) {
	cmdline, err := p.Cmdline()
	if err != nil {
		return nil, err
	}
	return strings.Split(cmdline, " "), nil
}

func (p *Process) CreateTime() (int64, error) {
	ru, err := getRusage(p.Pid)
	if err != nil {
		return 0, fmt.Errorf("could not get CreationDate: %s", err)
	}

	return ru.CreationTime.Nanoseconds() / 1000000, nil
}

func (p *Process) Cwd() (string, error) {
	return "", common.ErrNotImplementedError
}
func (p *Process) Parent() (*Process, error) {
	return p, common.ErrNotImplementedError
}
func (p *Process) Status() (string, error) {
	return "", common.ErrNotImplementedError
}
func (p *Process) Username() (string, error) {
	return "", common.ErrNotImplementedError
}
func (p *Process) Uids() ([]int32, error) {
	var uids []int32

	return uids, common.ErrNotImplementedError
}
func (p *Process) Gids() ([]int32, error) {
	var gids []int32
	return gids, common.ErrNotImplementedError
}
func (p *Process) Terminal() (string, error) {
	return "", common.ErrNotImplementedError
}

// Nice returnes priority in Windows
func (p *Process) Nice() (int32, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil {
		return 0, fmt.Errorf("could not get Priority: %s", err)
	}
	return int32(dst[0].Priority), nil
}
func (p *Process) IOnice() (int32, error) {
	return 0, common.ErrNotImplementedError
}
func (p *Process) Rlimit() ([]RlimitStat, error) {
	var rlimit []RlimitStat

	return rlimit, common.ErrNotImplementedError
}

func (p *Process) IOCounters() (*IOCountersStat, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil || len(dst) == 0 {
		return nil, fmt.Errorf("could not get Win32Proc: %s", err)
	}
	ret := &IOCountersStat{
		ReadCount:  uint64(dst[0].ReadOperationCount),
		ReadBytes:  uint64(dst[0].ReadTransferCount),
		WriteCount: uint64(dst[0].WriteOperationCount),
		WriteBytes: uint64(dst[0].WriteTransferCount),
	}

	return ret, nil
}
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
	return nil, common.ErrNotImplementedError
}
func (p *Process) NumFDs() (int32, error) {
	return 0, common.ErrNotImplementedError
}
func (p *Process) NumThreads() (int32, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil {
		return 0, fmt.Errorf("could not get ThreadCount: %s", err)
	}
	return int32(dst[0].ThreadCount), nil
}
func (p *Process) Threads() (map[string]string, error) {
	ret := make(map[string]string, 0)
	return ret, common.ErrNotImplementedError
}
func (p *Process) Times() (*cpu.TimesStat, error) {
	return nil, common.ErrNotImplementedError
}
func (p *Process) CPUAffinity() ([]int32, error) {
	return nil, common.ErrNotImplementedError
}
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
	mem, err := getMemoryInfo(p.Pid)
	if err != nil {
		return nil, err
	}

	ret := &MemoryInfoStat{
		RSS: mem.WorkingSetSize,
		VMS: mem.PagefileUsage,
	}

	return ret, nil
}
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
	return nil, common.ErrNotImplementedError
}

func (p *Process) Children() ([]*Process, error) {
	return nil, common.ErrNotImplementedError
}

func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
	return nil, common.ErrNotImplementedError
}

func (p *Process) Connections() ([]net.ConnectionStat, error) {
	return nil, common.ErrNotImplementedError
}

func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
	return nil, common.ErrNotImplementedError
}

func (p *Process) IsRunning() (bool, error) {
	return true, common.ErrNotImplementedError
}

func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
	var ret []MemoryMapsStat
	return &ret, common.ErrNotImplementedError
}

func NewProcess(pid int32) (*Process, error) {
	p := &Process{Pid: pid}

	return p, nil
}

func (p *Process) SendSignal(sig syscall.Signal) error {
	return common.ErrNotImplementedError
}

func (p *Process) Suspend() error {
	return common.ErrNotImplementedError
}
func (p *Process) Resume() error {
	return common.ErrNotImplementedError
}
func (p *Process) Terminate() error {
	return common.ErrNotImplementedError
}
func (p *Process) Kill() error {
	return common.ErrNotImplementedError
}

func (p *Process) getFromSnapProcess(pid int32) (int32, int32, string, error) {
	snap := w32.CreateToolhelp32Snapshot(w32.TH32CS_SNAPPROCESS, uint32(pid))
	if snap == 0 {
		return 0, 0, "", syscall.GetLastError()
	}
	defer w32.CloseHandle(snap)
	var pe32 w32.PROCESSENTRY32
	pe32.DwSize = uint32(unsafe.Sizeof(pe32))
	if w32.Process32First(snap, &pe32) == false {
		return 0, 0, "", syscall.GetLastError()
	}

	if pe32.Th32ProcessID == uint32(pid) {
		szexe := syscall.UTF16ToString(pe32.SzExeFile[:])
		return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil
	}

	for w32.Process32Next(snap, &pe32) {
		if pe32.Th32ProcessID == uint32(pid) {
			szexe := syscall.UTF16ToString(pe32.SzExeFile[:])
			return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil
		}
	}
	return 0, 0, "", errors.New("Couldn't find pid:" + string(pid))
}

// Get processes
func processes() ([]*Process, error) {

	var dst []Win32_Process
	q := wmi.CreateQuery(&dst, "")
	err := wmi.Query(q, &dst)
	if err != nil {
		return []*Process{}, err
	}
	if len(dst) == 0 {
		return []*Process{}, fmt.Errorf("could not get Process")
	}
	results := make([]*Process, 0, len(dst))
	for _, proc := range dst {
		p, err := NewProcess(int32(proc.ProcessID))
		if err != nil {
			continue
		}
		results = append(results, p)
	}

	return results, nil
}

func getProcInfo(pid int32) (*SystemProcessInformation, error) {
	initialBufferSize := uint64(0x4000)
	bufferSize := initialBufferSize
	buffer := make([]byte, bufferSize)

	var sysProcInfo SystemProcessInformation
	ret, _, _ := common.ProcNtQuerySystemInformation.Call(
		uintptr(unsafe.Pointer(&sysProcInfo)),
		uintptr(unsafe.Pointer(&buffer[0])),
		uintptr(unsafe.Pointer(&bufferSize)),
		uintptr(unsafe.Pointer(&bufferSize)))
	if ret != 0 {
		return nil, syscall.GetLastError()
	}

	return &sysProcInfo, nil
}

func getRusage(pid int32) (*syscall.Rusage, error) {
	var CPU syscall.Rusage

	c, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
	if err != nil {
		return nil, err
	}
	defer syscall.CloseHandle(c)

	if err := syscall.GetProcessTimes(c, &CPU.CreationTime, &CPU.ExitTime, &CPU.KernelTime, &CPU.UserTime); err != nil {
		return nil, err
	}

	return &CPU, nil
}

func getMemoryInfo(pid int32) (PROCESS_MEMORY_COUNTERS, error) {
	var mem PROCESS_MEMORY_COUNTERS
	c, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
	if err != nil {
		return mem, err
	}
	defer syscall.CloseHandle(c)
	if err := getProcessMemoryInfo(c, &mem); err != nil {
		return mem, err
	}

	return mem, err
}

func getProcessMemoryInfo(h syscall.Handle, mem *PROCESS_MEMORY_COUNTERS) (err error) {
	r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(h), uintptr(unsafe.Pointer(mem)), uintptr(unsafe.Sizeof(*mem)))
	if r1 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}
<commit_msg>Casting the values of working set and page file to uint64<commit_after>// +build windows

package process

import (
	"errors"
	"fmt"
	"strings"
	"syscall"
	"time"
	"unsafe"

	"github.com/StackExchange/wmi"
	"github.com/shirou/w32"

	cpu "github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/internal/common"
	net "github.com/shirou/gopsutil/net"
)

const (
	NoMoreFiles   = 0x12
	MaxPathLength = 260
)

var (
	modpsapi                 = syscall.NewLazyDLL("psapi.dll")
	procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
)

type SystemProcessInformation struct {
	NextEntryOffset   uint64
	NumberOfThreads   uint64
	Reserved1         [48]byte
	Reserved2         [3]byte
	UniqueProcessID   uintptr
	Reserved3         uintptr
	HandleCount       uint64
	Reserved4         [4]byte
	Reserved5         [11]byte
	PeakPagefileUsage uint64
	PrivatePageCount  uint64
	Reserved6         [6]uint64
}

// Memory_info_ex is different between OSes
type MemoryInfoExStat struct {
}

type MemoryMapsStat struct {
}

type Win32_Process struct {
	Name                string
	ExecutablePath      *string
	CommandLine         *string
	Priority            uint32
	CreationDate        *time.Time
	ProcessID           uint32
	ThreadCount         uint32
	Status              *string
	ReadOperationCount  uint64
	ReadTransferCount   uint64
	WriteOperationCount uint64
	WriteTransferCount  uint64

	/*
		CSCreationClassName   string
		CSName                string
		Caption               *string
		CreationClassName     string
		Description           *string
		ExecutionState        *uint16
		HandleCount           uint32
		KernelModeTime        uint64
		MaximumWorkingSetSize *uint32
		MinimumWorkingSetSize *uint32
		OSCreationClassName   string
		OSName                string
		OtherOperationCount   uint64
		OtherTransferCount    uint64
		PageFaults            uint32
		PageFileUsage         uint32
		ParentProcessID       uint32
		PeakPageFileUsage     uint32
		PeakVirtualSize       uint64
		PeakWorkingSetSize    uint32
		PrivatePageCount      uint64
		TerminationDate       *time.Time
		UserModeTime          uint64
		WorkingSetSize        uint64
	*/
}

func Pids() ([]int32, error) {
	var ret []int32

	procs, err := processes()
	if err != nil {
		return ret, nil
	}

	for _, proc := range procs {
		ret = append(ret, proc.Pid)
	}

	return ret, nil
}

func (p *Process) Ppid() (int32, error) {
	ret, _, _, err := p.getFromSnapProcess(p.Pid)
	if err != nil {
		return 0, err
	}
	return ret, nil
}

func GetWin32Proc(pid int32) ([]Win32_Process, error) {
	var dst []Win32_Process
	query := fmt.Sprintf("WHERE ProcessId = %d", pid)
	q := wmi.CreateQuery(&dst, query)
	err := wmi.Query(q, &dst)
	if err != nil {
		return []Win32_Process{}, fmt.Errorf("could not get win32Proc: %s", err)
	}
	if len(dst) != 1 {
		return []Win32_Process{}, fmt.Errorf("could not get win32Proc: empty")
	}
	return dst, nil
}

func (p *Process) Name() (string, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil {
		return "", fmt.Errorf("could not get Name: %s", err)
	}
	return dst[0].Name, nil
}
func (p *Process) Exe() (string, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil {
		return "", fmt.Errorf("could not get ExecutablePath: %s", err)
	}
	return *dst[0].ExecutablePath, nil
}
func (p *Process) Cmdline() (string, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil {
		return "", fmt.Errorf("could not get CommandLine: %s", err)
	}
	return *dst[0].CommandLine, nil
}

// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument. This merely returns the CommandLine informations passed
// to the process split on the 0x20 ASCII character.
func (p *Process) CmdlineSlice() ([]string, error) {
	cmdline, err := p.Cmdline()
	if err != nil {
		return nil, err
	}
	return strings.Split(cmdline, " "), nil
}

func (p *Process) CreateTime() (int64, error) {
	ru, err := getRusage(p.Pid)
	if err != nil {
		return 0, fmt.Errorf("could not get CreationDate: %s", err)
	}

	return ru.CreationTime.Nanoseconds() / 1000000, nil
}

func (p *Process) Cwd() (string, error) {
	return "", common.ErrNotImplementedError
}
func (p *Process) Parent() (*Process, error) {
	return p, common.ErrNotImplementedError
}
func (p *Process) Status() (string, error) {
	return "", common.ErrNotImplementedError
}
func (p *Process) Username() (string, error) {
	return "", common.ErrNotImplementedError
}
func (p *Process) Uids() ([]int32, error) {
	var uids []int32

	return uids, common.ErrNotImplementedError
}
func (p *Process) Gids() ([]int32, error) {
	var gids []int32
	return gids, common.ErrNotImplementedError
}
func (p *Process) Terminal() (string, error) {
	return "", common.ErrNotImplementedError
}

// Nice returnes priority in Windows
func (p *Process) Nice() (int32, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil {
		return 0, fmt.Errorf("could not get Priority: %s", err)
	}
	return int32(dst[0].Priority), nil
}
func (p *Process) IOnice() (int32, error) {
	return 0, common.ErrNotImplementedError
}
func (p *Process) Rlimit() ([]RlimitStat, error) {
	var rlimit []RlimitStat

	return rlimit, common.ErrNotImplementedError
}

func (p *Process) IOCounters() (*IOCountersStat, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil || len(dst) == 0 {
		return nil, fmt.Errorf("could not get Win32Proc: %s", err)
	}
	ret := &IOCountersStat{
		ReadCount:  uint64(dst[0].ReadOperationCount),
		ReadBytes:  uint64(dst[0].ReadTransferCount),
		WriteCount: uint64(dst[0].WriteOperationCount),
		WriteBytes: uint64(dst[0].WriteTransferCount),
	}

	return ret, nil
}
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
	return nil, common.ErrNotImplementedError
}
func (p *Process) NumFDs() (int32, error) {
	return 0, common.ErrNotImplementedError
}
func (p *Process) NumThreads() (int32, error) {
	dst, err := GetWin32Proc(p.Pid)
	if err != nil {
		return 0, fmt.Errorf("could not get ThreadCount: %s", err)
	}
	return int32(dst[0].ThreadCount), nil
}
func (p *Process) Threads() (map[string]string, error) {
	ret := make(map[string]string, 0)
	return ret, common.ErrNotImplementedError
}
func (p *Process) Times() (*cpu.TimesStat, error) {
	return nil, common.ErrNotImplementedError
}
func (p *Process) CPUAffinity() ([]int32, error) {
	return nil, common.ErrNotImplementedError
}
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
	mem, err := getMemoryInfo(p.Pid)
	if err != nil {
		return nil, err
	}

	ret := &MemoryInfoStat{
		RSS: uint64(mem.WorkingSetSize),
		VMS: uint64(mem.PagefileUsage),
	}

	return ret, nil
}
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
	return nil, common.ErrNotImplementedError
}

func (p *Process) Children() ([]*Process, error) {
	return nil, common.ErrNotImplementedError
}

func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
	return nil, common.ErrNotImplementedError
}

func (p *Process) Connections() ([]net.ConnectionStat, error) {
	return nil, common.ErrNotImplementedError
}

func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
	return nil, common.ErrNotImplementedError
}

func (p *Process) IsRunning() (bool, error) {
	return true, common.ErrNotImplementedError
}

func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
	var ret []MemoryMapsStat
	return &ret, common.ErrNotImplementedError
}

func NewProcess(pid int32) (*Process, error) {
	p := &Process{Pid: pid}

	return p, nil
}

func (p *Process) SendSignal(sig syscall.Signal) error {
	return common.ErrNotImplementedError
}

func (p *Process) Suspend() error {
	return common.ErrNotImplementedError
}
func (p *Process) Resume() error {
	return common.ErrNotImplementedError
}
func (p *Process) Terminate() error {
	return common.ErrNotImplementedError
}
func (p *Process) Kill() error {
	return common.ErrNotImplementedError
}

func (p *Process) getFromSnapProcess(pid int32) (int32, int32, string, error) {
	snap := w32.CreateToolhelp32Snapshot(w32.TH32CS_SNAPPROCESS, uint32(pid))
	if snap == 0 {
		return 0, 0, "", syscall.GetLastError()
	}
	defer w32.CloseHandle(snap)
	var pe32 w32.PROCESSENTRY32
	pe32.DwSize = uint32(unsafe.Sizeof(pe32))
	if w32.Process32First(snap, &pe32) == false {
		return 0, 0, "", syscall.GetLastError()
	}

	if pe32.Th32ProcessID == uint32(pid) {
		szexe := syscall.UTF16ToString(pe32.SzExeFile[:])
		return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil
	}

	for w32.Process32Next(snap, &pe32) {
		if pe32.Th32ProcessID == uint32(pid) {
			szexe := syscall.UTF16ToString(pe32.SzExeFile[:])
			return int32(pe32.Th32ParentProcessID), int32(pe32.CntThreads), szexe, nil
		}
	}
	return 0, 0, "", errors.New("Couldn't find pid:" + string(pid))
}

// Get processes
func processes() ([]*Process, error) {

	var dst []Win32_Process
	q := wmi.CreateQuery(&dst, "")
	err := wmi.Query(q, &dst)
	if err != nil {
		return []*Process{}, err
	}
	if len(dst) == 0 {
		return []*Process{}, fmt.Errorf("could not get Process")
	}
	results := make([]*Process, 0, len(dst))
	for _, proc := range dst {
		p, err := NewProcess(int32(proc.ProcessID))
		if err != nil {
			continue
		}
		results = append(results, p)
	}

	return results, nil
}

func getProcInfo(pid int32) (*SystemProcessInformation, error) {
	initialBufferSize := uint64(0x4000)
	bufferSize := initialBufferSize
	buffer := make([]byte, bufferSize)

	var sysProcInfo SystemProcessInformation
	ret, _, _ := common.ProcNtQuerySystemInformation.Call(
		uintptr(unsafe.Pointer(&sysProcInfo)),
		uintptr(unsafe.Pointer(&buffer[0])),
		uintptr(unsafe.Pointer(&bufferSize)),
		uintptr(unsafe.Pointer(&bufferSize)))
	if ret != 0 {
		return nil, syscall.GetLastError()
	}

	return &sysProcInfo, nil
}

func getRusage(pid int32) (*syscall.Rusage, error) {
	var CPU syscall.Rusage

	c, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
	if err != nil {
		return nil, err
	}
	defer syscall.CloseHandle(c)

	if err := syscall.GetProcessTimes(c, &CPU.CreationTime, &CPU.ExitTime, &CPU.KernelTime, &CPU.UserTime); err != nil {
		return nil, err
	}

	return &CPU, nil
}

func getMemoryInfo(pid int32) (PROCESS_MEMORY_COUNTERS, error) {
	var mem PROCESS_MEMORY_COUNTERS
	c, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
	if err != nil {
		return mem, err
	}
	defer syscall.CloseHandle(c)
	if err := getProcessMemoryInfo(c, &mem); err != nil {
		return mem, err
	}

	return mem, err
}

func getProcessMemoryInfo(h syscall.Handle, mem *PROCESS_MEMORY_COUNTERS) (err error) {
	r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(h), uintptr(unsafe.Pointer(mem)), uintptr(unsafe.Sizeof(*mem)))
	if r1 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	return
}
<|endoftext|>


<commit_before>package alog

import (
	"fmt"
	"os"

	"github.com/antlinker/alog/utils"

	"github.com/antlinker/alog/log"
	"github.com/antlinker/alog/manage"
)

// ALog 提供ALog日志模块的输出管理
type ALog struct {
	tag    log.LogTag
	config *log.LogConfig
	manage log.LogManage
}

// NewALog 获取ALog实例
// configs 配置文件路径
func NewALog(configs ...string) *ALog {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("===> [ALog]Initialization error:", err)
			os.Exit(-1)
		}
	}()
	config := loadDefaultConfig()
	if len(configs) > 0 {
		err := utils.NewConfig(configs[0]).Read(config)
		if err != nil {
			panic(err)
		}
	} else if gLg := GALog; gLg != nil {
		config = &(*(gLg.GetConfig()))
	}
	return &ALog{
		config: config,
		manage: manage.NewLogManage(config),
		tag:    log.DefaultTag,
	}
}

// SetLogTag 设置LogTag
func (a *ALog) SetLogTag(tag string) {
	a.tag = log.LogTag(tag)
}

// SetLogLevel 设置日志输出级别
func (a *ALog) SetLogLevel(level log.LogLevel) {
	a.config.Global.Level = level
}

// SetShowFile 设置输出文件信息
func (a *ALog) SetShowFile(v bool) {
	show := 2
	if v {
		show = 1
	}
	a.config.Global.ShowFile = show
}

// SetFileCaller 设置文件调用层次
func (a *ALog) SetFileCaller(caller int) {
	a.config.Global.FileCaller = caller
}

// SetRule 设置输出规则
func (a *ALog) SetRule(rule log.LogRule) {
	a.config.Global.Rule = rule
}

// SetEnabled 设置是否启用日志
func (a *ALog) SetEnabled(enabled bool) {
	v := 2
	if enabled {
		v = 1
	}
	a.config.Global.IsEnabled = v
}

// SetPrint 设置控制台输出日志
func (a *ALog) SetPrint(v bool) {
	vv := 2
	if v {
		vv = 1
	}
	a.config.Global.IsPrint = vv
}

// ReloadConfig 重置加载配置文件
func (a *ALog) ReloadConfig(cfg string) error {
	config := loadDefaultConfig()
	err := utils.NewConfig(cfg).Read(config)
	if err != nil {
		return err
	}
	a.config = config
	return nil
}

// GetConfig 获取配置文件信息
func (a *ALog) GetConfig() *log.LogConfig {
	return a.config
}

// GetWriteNum 获取写入持久化日志条数
func (a *ALog) GetWriteNum() int64 {
	return a.manage.TotalNum()
}

// Write 输出消息
func (a *ALog) Write(onlyConsole bool, level log.LogLevel, tag string, v ...interface{}) {
	if a.config.Global.IsEnabled != 1 {
		return
	}
	t := log.LogTag(tag)
	if t == "" {
		t = a.tag
	}
	if onlyConsole {
		a.manage.Console(level, t, v...)
		return
	}
	a.manage.Write(level, t, v...)
}

// Writef 输出格式化消息
func (a *ALog) Writef(onlyConsole bool, level log.LogLevel, tag string, format string, v ...interface{}) {
	if a.config.Global.IsEnabled != 1 {
		return
	}
	t := log.LogTag(tag)
	if t == "" {
		t = a.tag
	}
	if onlyConsole {
		a.manage.Consolef(level, t, format, v...)
		return
	}
	a.manage.Writef(level, t, format, v...)
}

func (a *ALog) Debug(v ...interface{}) {
	a.Write(false, log.DEBUG, "", v...)
}

func (a *ALog) Debugf(format string, v ...interface{}) {
	a.Writef(false, log.DEBUG, "", format, v...)
}

func (a *ALog) DebugT(tag string, v ...interface{}) {
	a.Write(false, log.DEBUG, tag, v...)
}

func (a *ALog) DebugTf(tag string, format string, v ...interface{}) {
	a.Writef(false, log.DEBUG, tag, format, v...)
}

func (a *ALog) DebugC(v ...interface{}) {
	a.Write(true, log.DEBUG, "", v...)
}

func (a *ALog) DebugCf(format string, v ...interface{}) {
	a.Writef(true, log.DEBUG, "", format, v...)
}

func (a *ALog) DebugTC(tag string, v ...interface{}) {
	a.Write(true, log.DEBUG, tag, v...)
}

func (a *ALog) DebugTCf(tag string, format string, v ...interface{}) {
	a.Writef(true, log.DEBUG, tag, format, v...)
}

func (a *ALog) Info(v ...interface{}) {
	a.Write(false, log.INFO, "", v...)
}

func (a *ALog) Infof(format string, v ...interface{}) {
	a.Writef(false, log.INFO, "", format, v...)
}

func (a *ALog) InfoT(tag string, v ...interface{}) {
	a.Write(false, log.INFO, tag, v...)
}

func (a *ALog) InfoTf(tag string, format string, v ...interface{}) {
	a.Writef(false, log.INFO, tag, format, v...)
}

func (a *ALog) InfoC(v ...interface{}) {
	a.Write(true, log.INFO, "", v...)
}

func (a *ALog) InfoCf(format string, v ...interface{}) {
	a.Writef(true, log.INFO, "", format, v...)
}

func (a *ALog) InfoTC(tag string, v ...interface{}) {
	a.Write(true, log.INFO, tag, v...)
}

func (a *ALog) InfoTCf(tag string, format string, v ...interface{}) {
	a.Writef(true, log.INFO, tag, format, v...)
}

func (a *ALog) Warn(v ...interface{}) {
	a.Write(false, log.WARN, "", v...)
}

func (a *ALog) Warnf(format string, v ...interface{}) {
	a.Writef(false, log.WARN, "", format, v...)
}

func (a *ALog) WarnT(tag string, v ...interface{}) {
	a.Write(false, log.WARN, tag, v...)
}

func (a *ALog) WarnTf(tag string, format string, v ...interface{}) {
	a.Writef(false, log.WARN, tag, format, v...)
}

func (a *ALog) WarnC(v ...interface{}) {
	a.Write(true, log.WARN, "", v...)
}

func (a *ALog) WarnCf(format string, v ...interface{}) {
	a.Writef(true, log.WARN, "", format, v...)
}

func (a *ALog) WarnTC(tag string, v ...interface{}) {
	a.Write(true, log.WARN, tag, v...)
}

func (a *ALog) WarnTCf(tag string, format string, v ...interface{}) {
	a.Writef(true, log.WARN, tag, format, v...)
}

func (a *ALog) Error(v ...interface{}) {
	a.Write(false, log.ERROR, "", v...)
}

func (a *ALog) Errorf(format string, v ...interface{}) {
	a.Writef(false, log.ERROR, "", format, v...)
}

func (a *ALog) ErrorT(tag string, v ...interface{}) {
	a.Write(false, log.ERROR, tag, v...)
}

func (a *ALog) ErrorTf(tag string, format string, v ...interface{}) {
	a.Writef(false, log.ERROR, tag, format, v...)
}

func (a *ALog) ErrorC(v ...interface{}) {
	a.Write(true, log.ERROR, "", v...)
}

func (a *ALog) ErrorCf(format string, v ...interface{}) {
	a.Writef(true, log.ERROR, "", format, v...)
}

func (a *ALog) ErrorTC(tag string, v ...interface{}) {
	a.Write(true, log.ERROR, tag, v...)
}

func (a *ALog) ErrorTCf(tag string, format string, v ...interface{}) {
	a.Writef(true, log.ERROR, tag, format, v...)
}

func (a *ALog) Fatal(v ...interface{}) {
	a.Write(false, log.FATAL, "", v...)
}

func (a *ALog) Fatalf(format string, v ...interface{}) {
	a.Writef(false, log.FATAL, "", format, v...)
}

func (a *ALog) FatalT(tag string, v ...interface{}) {
	a.Write(false, log.FATAL, tag, v...)
}

func (a *ALog) FatalTf(tag string, format string, v ...interface{}) {
	a.Writef(false, log.FATAL, tag, format, v...)
}

func (a *ALog) FatalC(v ...interface{}) {
	a.Write(true, log.FATAL, "", v...)
}

func (a *ALog) FatalCf(format string, v ...interface{}) {
	a.Writef(true, log.FATAL, "", format, v...)
}

func (a *ALog) FatalTC(tag string, v ...interface{}) {
	a.Write(true, log.FATAL, tag, v...)
}

func (a *ALog) FatalTCf(tag string, format string, v ...interface{}) {
	a.Writef(true, log.FATAL, tag, format, v...)
}
<commit_msg>Fixed ReloadConfig func<commit_after>package alog

import (
	"fmt"
	"os"

	"github.com/antlinker/alog/utils"

	"github.com/antlinker/alog/log"
	"github.com/antlinker/alog/manage"
)

// ALog 提供ALog日志模块的输出管理
type ALog struct {
	tag    log.LogTag
	config *log.LogConfig
	manage log.LogManage
}

// NewALog 获取ALog实例
// configs 配置文件路径
func NewALog(configs ...string) *ALog {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("===> [ALog]Initialization error:", err)
			os.Exit(-1)
		}
	}()
	config := loadDefaultConfig()
	if len(configs) > 0 {
		err := utils.NewConfig(configs[0]).Read(config)
		if err != nil {
			panic(err)
		}
	} else if gLg := GALog; gLg != nil {
		config = &(*(gLg.GetConfig()))
	}
	return &ALog{
		config: config,
		manage: manage.NewLogManage(config),
		tag:    log.DefaultTag,
	}
}

// SetLogTag 设置LogTag
func (a *ALog) SetLogTag(tag string) {
	a.tag = log.LogTag(tag)
}

// SetLogLevel 设置日志输出级别
func (a *ALog) SetLogLevel(level log.LogLevel) {
	a.config.Global.Level = level
}

// SetShowFile 设置输出文件信息
func (a *ALog) SetShowFile(v bool) {
	show := 2
	if v {
		show = 1
	}
	a.config.Global.ShowFile = show
}

// SetFileCaller 设置文件调用层次
func (a *ALog) SetFileCaller(caller int) {
	a.config.Global.FileCaller = caller
}

// SetRule 设置输出规则
func (a *ALog) SetRule(rule log.LogRule) {
	a.config.Global.Rule = rule
}

// SetEnabled 设置是否启用日志
func (a *ALog) SetEnabled(enabled bool) {
	v := 2
	if enabled {
		v = 1
	}
	a.config.Global.IsEnabled = v
}

// SetPrint 设置控制台输出日志
func (a *ALog) SetPrint(v bool) {
	vv := 2
	if v {
		vv = 1
	}
	a.config.Global.IsPrint = vv
}

// ReloadConfig 重置加载配置文件
func (a *ALog) ReloadConfig(cfg string) error {
	config := loadDefaultConfig()
	err := utils.NewConfig(cfg).Read(config)
	if err != nil {
		return err
	}
	a.config = config
	a.manage = manage.NewLogManage(config)
	return nil
}

// GetConfig 获取配置文件信息
func (a *ALog) GetConfig() *log.LogConfig {
	return a.config
}

// GetWriteNum 获取写入持久化日志条数
func (a *ALog) GetWriteNum() int64 {
	return a.manage.TotalNum()
}

// Write 输出消息
func (a *ALog) Write(onlyConsole bool, level log.LogLevel, tag string, v ...interface{}) {
	if a.config.Global.IsEnabled != 1 {
		return
	}
	t := log.LogTag(tag)
	if t == "" {
		t = a.tag
	}
	if onlyConsole {
		a.manage.Console(level, t, v...)
		return
	}
	a.manage.Write(level, t, v...)
}

// Writef 输出格式化消息
func (a *ALog) Writef(onlyConsole bool, level log.LogLevel, tag string, format string, v ...interface{}) {
	if a.config.Global.IsEnabled != 1 {
		return
	}
	t := log.LogTag(tag)
	if t == "" {
		t = a.tag
	}
	if onlyConsole {
		a.manage.Consolef(level, t, format, v...)
		return
	}
	a.manage.Writef(level, t, format, v...)
}

func (a *ALog) Debug(v ...interface{}) {
	a.Write(false, log.DEBUG, "", v...)
}

func (a *ALog) Debugf(format string, v ...interface{}) {
	a.Writef(false, log.DEBUG, "", format, v...)
}

func (a *ALog) DebugT(tag string, v ...interface{}) {
	a.Write(false, log.DEBUG, tag, v...)
}

func (a *ALog) DebugTf(tag string, format string, v ...interface{}) {
	a.Writef(false, log.DEBUG, tag, format, v...)
}

func (a *ALog) DebugC(v ...interface{}) {
	a.Write(true, log.DEBUG, "", v...)
}

func (a *ALog) DebugCf(format string, v ...interface{}) {
	a.Writef(true, log.DEBUG, "", format, v...)
}

func (a *ALog) DebugTC(tag string, v ...interface{}) {
	a.Write(true, log.DEBUG, tag, v...)
}

func (a *ALog) DebugTCf(tag string, format string, v ...interface{}) {
	a.Writef(true, log.DEBUG, tag, format, v...)
}

func (a *ALog) Info(v ...interface{}) {
	a.Write(false, log.INFO, "", v...)
}

func (a *ALog) Infof(format string, v ...interface{}) {
	a.Writef(false, log.INFO, "", format, v...)
}

func (a *ALog) InfoT(tag string, v ...interface{}) {
	a.Write(false, log.INFO, tag, v...)
}

func (a *ALog) InfoTf(tag string, format string, v ...interface{}) {
	a.Writef(false, log.INFO, tag, format, v...)
}

func (a *ALog) InfoC(v ...interface{}) {
	a.Write(true, log.INFO, "", v...)
}

func (a *ALog) InfoCf(format string, v ...interface{}) {
	a.Writef(true, log.INFO, "", format, v...)
}

func (a *ALog) InfoTC(tag string, v ...interface{}) {
	a.Write(true, log.INFO, tag, v...)
}

func (a *ALog) InfoTCf(tag string, format string, v ...interface{}) {
	a.Writef(true, log.INFO, tag, format, v...)
}

func (a *ALog) Warn(v ...interface{}) {
	a.Write(false, log.WARN, "", v...)
}

func (a *ALog) Warnf(format string, v ...interface{}) {
	a.Writef(false, log.WARN, "", format, v...)
}

func (a *ALog) WarnT(tag string, v ...interface{}) {
	a.Write(false, log.WARN, tag, v...)
}

func (a *ALog) WarnTf(tag string, format string, v ...interface{}) {
	a.Writef(false, log.WARN, tag, format, v...)
}

func (a *ALog) WarnC(v ...interface{}) {
	a.Write(true, log.WARN, "", v...)
}

func (a *ALog) WarnCf(format string, v ...interface{}) {
	a.Writef(true, log.WARN, "", format, v...)
}

func (a *ALog) WarnTC(tag string, v ...interface{}) {
	a.Write(true, log.WARN, tag, v...)
}

func (a *ALog) WarnTCf(tag string, format string, v ...interface{}) {
	a.Writef(true, log.WARN, tag, format, v...)
}

func (a *ALog) Error(v ...interface{}) {
	a.Write(false, log.ERROR, "", v...)
}

func (a *ALog) Errorf(format string, v ...interface{}) {
	a.Writef(false, log.ERROR, "", format, v...)
}

func (a *ALog) ErrorT(tag string, v ...interface{}) {
	a.Write(false, log.ERROR, tag, v...)
}

func (a *ALog) ErrorTf(tag string, format string, v ...interface{}) {
	a.Writef(false, log.ERROR, tag, format, v...)
}

func (a *ALog) ErrorC(v ...interface{}) {
	a.Write(true, log.ERROR, "", v...)
}

func (a *ALog) ErrorCf(format string, v ...interface{}) {
	a.Writef(true, log.ERROR, "", format, v...)
}

func (a *ALog) ErrorTC(tag string, v ...interface{}) {
	a.Write(true, log.ERROR, tag, v...)
}

func (a *ALog) ErrorTCf(tag string, format string, v ...interface{}) {
	a.Writef(true, log.ERROR, tag, format, v...)
}

func (a *ALog) Fatal(v ...interface{}) {
	a.Write(false, log.FATAL, "", v...)
}

func (a *ALog) Fatalf(format string, v ...interface{}) {
	a.Writef(false, log.FATAL, "", format, v...)
}

func (a *ALog) FatalT(tag string, v ...interface{}) {
	a.Write(false, log.FATAL, tag, v...)
}

func (a *ALog) FatalTf(tag string, format string, v ...interface{}) {
	a.Writef(false, log.FATAL, tag, format, v...)
}

func (a *ALog) FatalC(v ...interface{}) {
	a.Write(true, log.FATAL, "", v...)
}

func (a *ALog) FatalCf(format string, v ...interface{}) {
	a.Writef(true, log.FATAL, "", format, v...)
}

func (a *ALog) FatalTC(tag string, v ...interface{}) {
	a.Write(true, log.FATAL, tag, v...)
}

func (a *ALog) FatalTCf(tag string, format string, v ...interface{}) {
	a.Writef(true, log.FATAL, tag, format, v...)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path"
	"time"
)

type Logfile struct {
	baseDir string
	file *os.File
	name string
	nlines int
	maxlines int
}

func NewLogfile(baseDir string, maxlines int) (*Logfile) {
	return &Logfile{baseDir, nil, "", 0, maxlines}
}

func (lf *Logfile) Close() {
	if lf.file != nil {
		lf.writeln("EXIT")
		lf.file.Close()
	}
}

func (lf *Logfile) writeln(s string) error {
	_, err := fmt.Fprintf(lf.file, "%d %s\n", time.Now().Unix(), s)
	if err == nil {
		lf.nlines += 1
	}
	return err
}

func (lf *Logfile) rotate() error {
	fn := fmt.Sprintf("%s.log", time.Now().UTC().Format(time.RFC3339))
	pathn := path.Join(lf.baseDir, "log", fn)
	newf, err := os.OpenFile(pathn, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
	if err != nil {
		return err
	}

	if lf.file == nil {
		// Set lf.file just so we can write out NEXTLOG.
		// If this fails, that's okay
		lf.file, _ = os.OpenFile("current", os.O_WRONLY|os.O_APPEND, 0666)
	}

	if lf.file != nil {
		// Note location of new log
		logmsg := fmt.Sprintf(". NEXTLOG %s", fn)
		lf.writeln(logmsg)

		// All done with the current log
		lf.file.Close()
	}

	// Point to new log file
	lf.file = newf

	// Record symlink to new log
	os.Remove(path.Join(lf.baseDir, "log", "current"))
	os.Symlink(fn, path.Join(lf.baseDir, "log", "current"))

	logmsg := fmt.Sprintf(". PREVLOG %s", lf.name)
	lf.writeln(logmsg)

	lf.name = fn

	return nil
}

func (lf *Logfile) Log(s string) error {
	if lf.file == nil {
		lf.rotate()
	}

	err := lf.writeln(s)
	if err == nil {
		return err
	}

	if lf.nlines >= lf.maxlines {
		return lf.rotate()
	}

	return nil
}
<commit_msg>Fix NEXTLOG on restart<commit_after>package main

import (
	"fmt"
	"os"
	"path"
	"time"
)

type Logfile struct {
	baseDir string
	file *os.File
	name string
	nlines int
	maxlines int
}

func NewLogfile(baseDir string, maxlines int) (*Logfile) {
	return &Logfile{baseDir, nil, "", 0, maxlines}
}

func (lf *Logfile) Close() {
	if lf.file != nil {
		lf.writeln("EXIT")
		lf.file.Close()
	}
}

func (lf *Logfile) writeln(s string) error {
	_, err := fmt.Fprintf(lf.file, "%d %s\n", time.Now().Unix(), s)
	if err == nil {
		lf.nlines += 1
	}
	return err
}

func (lf *Logfile) rotate() error {
	fn := fmt.Sprintf("%s.log", time.Now().UTC().Format(time.RFC3339))
	pathn := path.Join(lf.baseDir, "log", fn)
	newf, err := os.OpenFile(pathn, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
	if err != nil {
		return err
	}

	currentPath = path.Join(lf.baseDir, "log", "current")

	if lf.file == nil {
		// Set lf.file just so we can write out NEXTLOG.
		// If this fails, that's okay
		lf.file, _ = os.OpenFile(currentPath, os.O_WRONLY|os.O_APPEND, 0666)
	}

	if lf.file != nil {
		// Note location of new log
		logmsg := fmt.Sprintf(". NEXTLOG %s", fn)
		lf.writeln(logmsg)

		// All done with the current log
		lf.file.Close()
	}

	// Point to new log file
	lf.file = newf

	// Record symlink to new log
	os.Remove(currentPath)
	os.Symlink(fn, currentPath)

	logmsg := fmt.Sprintf(". PREVLOG %s", lf.name)
	lf.writeln(logmsg)

	lf.name = fn

	return nil
}

func (lf *Logfile) Log(s string) error {
	if lf.file == nil {
		lf.rotate()
	}

	err := lf.writeln(s)
	if err == nil {
		return err
	}

	if lf.nlines >= lf.maxlines {
		return lf.rotate()
	}

	return nil
}
<|endoftext|>


<commit_before>package sprite

import (
	"bytes"
	"crypto/md5"
	"encoding/base64"
	"fmt"
	"image"
	"image/draw"
	"image/png"
	"io"
	"path/filepath"
	"strings"

	"github.com/redforks/css-1/scanner"
	"github.com/redforks/css/writer"
	"github.com/redforks/errors"
)

// Service provide/isolate I/O interface of Spriter.
type Service interface {
	// OpenImage opens image file as io.Reader, path is the relative path defined
	// in css. Spriter will close the io.Reader if it also implements io.Closer.
	OpenImage(path string) (io.Reader, error)

	// Create sprite image file return as io.Writer. Spriter will close the
	// io.Writer if it also implements io.Closer. path is relative to output css
	// file.
	CreateSpriteImage(path string) (io.Writer, error)
}

// Generate css sprite image by scan .css file, generate updated .css file.
//
// Image must use relative path, absolute path or other web site report as warning.
//
// Only png file supported, ignore other image file format.
//
// Image file name need to be in [Group].[Name].png format, images with the
// same group name will generate a sprite image [Group].png. Images without
// group name leave it untouched.
type Spriter struct {
	css string
	sv  Service

	loadedImages map[string]*stamp
}

// Create Spriter.
//
//  css: css file content
func New(css string, service Service) *Spriter {
	return &Spriter{
		css:          css,
		sv:           service,
		loadedImages: make(map[string]*stamp),
	}
}

// Do the generation, return translated css file content. Generated sprite
// image files are saved using Service interface.
func (s *Spriter) Gen() (css string, err error) {
	var tks []*scanner.Token
	tks, err = scan(s.css)
	if err != nil {
		return
	}

	needTranslate := false
	groups := make(map[string][]*cssImage)
	for _, tk := range tks {
		switch tk.Type {
		case scanner.TokenIdent:
			needTranslate = tk.Value == "background"
		case scanner.TokenURI:
			if needTranslate {
				var (
					st *cssImage
					g  string
				)
				if st, g, err = s.parseCssImage(tk); err != nil {
					return
				}

				if st != nil {
					groups[g] = append(groups[g], st)
				}
			}
		}
	}

	for _, sts := range groups {
		size := getSpriteSize(sts)
		var sprite = image.NewRGBA(image.Rectangle{Min: image.Point{}, Max: size})
		p := image.Pt(0, 0)
		for _, st := range sts {
			b := st.img.bounds()
			draw.Draw(sprite, b.Add(p), st.img.img, b.Min, draw.Src)
			p.X += st.img.dx()
		}

		hash := md5.New()
		buf := &bytes.Buffer{}
		w := io.MultiWriter(buf, hash)
		if err = png.Encode(w, sprite); err != nil {
			err = errors.NewRuntime(err)
			return
		}
		token := base64.URLEncoding.EncodeToString(hash.Sum(nil)[:6])

		var f io.Writer
		f, err = s.sv.CreateSpriteImage(token + ".png")
		if err != nil {
			return
		}
		defer closeClosable(f)
		if _, err = f.Write(buf.Bytes()); err != nil {
			return
		}

		for _, st := range sts {
			st.tk.Value = "url(" + token + ".png) no-repeat"
			if st.img.sp.X != 0 {
				st.tk.Value += fmt.Sprintf(" %dpx 0", st.img.sp.X)
			}
		}
	}

	return writer.Dumps(tks)
}

func getSpriteSize(imgs []*cssImage) image.Point {
	p := image.Point{}
	for _, img := range imgs {
		st := img.img
		if st.sp.X == -1 {
			st.sp = image.Pt(-p.X, 0)
			p.X += st.dx()
			if p.Y < st.dy() {
				p.Y = st.dy()
			}
		}
	}
	return p
}

// Call .Close() if object implements io.Closer.
func closeClosable(o interface{}) {
	closable, ok := o.(io.Closer)
	if ok {
		closable.Close()
	}
}

func scan(css string) ([]*scanner.Token, error) {
	s := scanner.New(css)
	tks := []*scanner.Token{}
	for {
		tk := s.Next()
		switch tk.Type {
		case scanner.TokenEOF:
			return tks, nil
		case scanner.TokenError:
			return nil, errors.Input(tk.Value)
		default:
			tks = append(tks, tk)
		}
	}
}

func extractUriFile(uri string) (file string, err error) {
	s := uri[4 : len(uri)-1]
	switch s[0] {
	case '"', '\'':
		s = s[1 : len(s)-1]
	}
	return s, nil
}

// extract file name, expect [group].[name].png. Group name is empty string if
// not expected format, or extension not supported
func extractGroup(path string) (group string) {
	words := strings.Split(filepath.Base(path), ".")
	if len(words) != 3 || words[2] != "png" {
		return
	}

	return words[0]
}

// Represent a css image style
type cssImage struct {
	tk  *scanner.Token
	img *stamp
}

// Represent a image inside sprite
type stamp struct {
	filename string // Filename of the image
	img      image.Image
	sp       image.Point // Start position in sprite
}

func (st *stamp) bounds() image.Rectangle {
	return st.img.Bounds()
}

func (st *stamp) dx() int {
	return st.img.Bounds().Dx()
}

func (st *stamp) dy() int {
	return st.img.Bounds().Dy()
}

// Parse stamp from a image url css token. stamp is nil if the url need
// ignored: not png, not expected filename format.
func (s *Spriter) parseCssImage(tk *scanner.Token) (cssImg *cssImage, groupName string, err error) {
	var fn string
	if fn, err = extractUriFile(tk.Value); err != nil {
		return
	}

	groupName = extractGroup(fn)
	if groupName == "" {
		return
	}

	var st *stamp
	if st, err = s.parseImage(fn); err != nil {
		return
	}

	cssImg = &cssImage{
		tk,
		st,
	}
	return
}

func (s *Spriter) parseImage(imgFile string) (*stamp, error) {
	if img, ok := s.loadedImages[imgFile]; ok {
		return img, nil
	}

	if f, err := s.sv.OpenImage(imgFile); err != nil {
		return nil, errors.NewInput(err)
	} else {
		defer closeClosable(f)

		img, _, err := image.Decode(f)
		if err != nil {
			return nil, errors.NewInput(err)
		}
		st := &stamp{
			imgFile,
			img,
			image.Pt(-1, -1),
		}
		s.loadedImages[imgFile] = st
		return st, nil
	}
}
<commit_msg>Fix sprite image if multiple rule ref same image file<commit_after>package sprite

import (
	"bytes"
	"crypto/md5"
	"encoding/base64"
	"fmt"
	"image"
	"image/draw"
	"image/png"
	"io"
	"path/filepath"
	"strings"

	"github.com/redforks/css-1/scanner"
	"github.com/redforks/css/writer"
	"github.com/redforks/errors"
)

// Service provide/isolate I/O interface of Spriter.
type Service interface {
	// OpenImage opens image file as io.Reader, path is the relative path defined
	// in css. Spriter will close the io.Reader if it also implements io.Closer.
	OpenImage(path string) (io.Reader, error)

	// Create sprite image file return as io.Writer. Spriter will close the
	// io.Writer if it also implements io.Closer. path is relative to output css
	// file.
	CreateSpriteImage(path string) (io.Writer, error)
}

// Generate css sprite image by scan .css file, generate updated .css file.
//
// Image must use relative path, absolute path or other web site report as warning.
//
// Only png file supported, ignore other image file format.
//
// Image file name need to be in [Group].[Name].png format, images with the
// same group name will generate a sprite image [Group].png. Images without
// group name leave it untouched.
type Spriter struct {
	css string
	sv  Service

	loadedImages map[string]*stamp
}

// Create Spriter.
//
//  css: css file content
func New(css string, service Service) *Spriter {
	return &Spriter{
		css:          css,
		sv:           service,
		loadedImages: make(map[string]*stamp),
	}
}

// Do the generation, return translated css file content. Generated sprite
// image files are saved using Service interface.
func (s *Spriter) Gen() (css string, err error) {
	var tks []*scanner.Token
	tks, err = scan(s.css)
	if err != nil {
		return
	}

	needTranslate := false
	groups := make(map[string][]*cssImage)
	for _, tk := range tks {
		switch tk.Type {
		case scanner.TokenIdent:
			needTranslate = tk.Value == "background"
		case scanner.TokenURI:
			if needTranslate {
				var (
					st *cssImage
					g  string
				)
				if st, g, err = s.parseCssImage(tk); err != nil {
					return
				}

				if st != nil {
					groups[g] = append(groups[g], st)
				}
			}
		}
	}

	for _, sts := range groups {
		size := getSpriteSize(sts)
		var sprite = image.NewRGBA(image.Rectangle{Min: image.Point{}, Max: size})
		for _, st := range sts {
			b := st.img.bounds()
			draw.Draw(sprite, b.Add(image.Pt(-st.img.sp.X, st.img.sp.Y)), st.img.img, b.Min, draw.Src)
		}

		hash := md5.New()
		buf := &bytes.Buffer{}
		w := io.MultiWriter(buf, hash)
		if err = png.Encode(w, sprite); err != nil {
			err = errors.NewRuntime(err)
			return
		}
		token := base64.URLEncoding.EncodeToString(hash.Sum(nil)[:6])

		var f io.Writer
		f, err = s.sv.CreateSpriteImage(token + ".png")
		if err != nil {
			return
		}
		defer closeClosable(f)
		if _, err = f.Write(buf.Bytes()); err != nil {
			return
		}

		for _, st := range sts {
			st.tk.Value = "url(" + token + ".png) no-repeat"
			if st.img.sp.X != 0 {
				st.tk.Value += fmt.Sprintf(" %dpx 0", st.img.sp.X)
			}
		}
	}

	return writer.Dumps(tks)
}

func getSpriteSize(imgs []*cssImage) image.Point {
	p := image.Point{}
	for _, img := range imgs {
		st := img.img
		if st.sp.X == -1 {
			st.sp = image.Pt(-p.X, 0)
			p.X += st.dx()
			if p.Y < st.dy() {
				p.Y = st.dy()
			}
		}
	}
	return p
}

// Call .Close() if object implements io.Closer.
func closeClosable(o interface{}) {
	closable, ok := o.(io.Closer)
	if ok {
		closable.Close()
	}
}

func scan(css string) ([]*scanner.Token, error) {
	s := scanner.New(css)
	tks := []*scanner.Token{}
	for {
		tk := s.Next()
		switch tk.Type {
		case scanner.TokenEOF:
			return tks, nil
		case scanner.TokenError:
			return nil, errors.Input(tk.Value)
		default:
			tks = append(tks, tk)
		}
	}
}

func extractUriFile(uri string) (file string, err error) {
	s := uri[4 : len(uri)-1]
	switch s[0] {
	case '"', '\'':
		s = s[1 : len(s)-1]
	}
	return s, nil
}

// extract file name, expect [group].[name].png. Group name is empty string if
// not expected format, or extension not supported
func extractGroup(path string) (group string) {
	words := strings.Split(filepath.Base(path), ".")
	if len(words) != 3 || words[2] != "png" {
		return
	}

	return words[0]
}

// Represent a css image style
type cssImage struct {
	tk  *scanner.Token
	img *stamp
}

// Represent a image inside sprite
type stamp struct {
	filename string // Filename of the image
	img      image.Image
	sp       image.Point // Start position in sprite
}

func (st *stamp) bounds() image.Rectangle {
	return st.img.Bounds()
}

func (st *stamp) dx() int {
	return st.img.Bounds().Dx()
}

func (st *stamp) dy() int {
	return st.img.Bounds().Dy()
}

// Parse stamp from a image url css token. stamp is nil if the url need
// ignored: not png, not expected filename format.
func (s *Spriter) parseCssImage(tk *scanner.Token) (cssImg *cssImage, groupName string, err error) {
	var fn string
	if fn, err = extractUriFile(tk.Value); err != nil {
		return
	}

	groupName = extractGroup(fn)
	if groupName == "" {
		return
	}

	var st *stamp
	if st, err = s.parseImage(fn); err != nil {
		return
	}

	cssImg = &cssImage{
		tk,
		st,
	}
	return
}

func (s *Spriter) parseImage(imgFile string) (*stamp, error) {
	if img, ok := s.loadedImages[imgFile]; ok {
		return img, nil
	}

	if f, err := s.sv.OpenImage(imgFile); err != nil {
		return nil, errors.NewInput(err)
	} else {
		defer closeClosable(f)

		img, _, err := image.Decode(f)
		if err != nil {
			return nil, errors.NewInput(err)
		}
		st := &stamp{
			imgFile,
			img,
			image.Pt(-1, -1),
		}
		s.loadedImages[imgFile] = st
		return st, nil
	}
}
<|endoftext|>


<commit_before>package steam

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
)

type Apps struct {
	List AppList `json:"applist"`
}

type AppList struct {
	Apps []App `json:"apps"`
}

type App struct {
	AppID int    `json:"appid"`
	Name  string `json:"name"`
}

// Get list of all apps along with their App IDs in JSON format
func (s *Steam) GetAppList() (*Apps, error) {
	res, err := http.Get(BaseURL + "/ISteamApps/GetAppList/v2?format=json")
	if err != nil {
		return nil, err
	}

	defer res.Body.Close()
	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	apps := new(Apps)
	err = json.Unmarshal(data, &apps)
	if err != nil {
		return nil, err
	}

	return apps, nil
}
<commit_msg>Rename the comments<commit_after>package steam

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
)

type Apps struct {
	List AppList `json:"applist"`
}

type AppList struct {
	Apps []App `json:"apps"`
}

type App struct {
	AppID int    `json:"appid"`
	Name  string `json:"name"`
}

// Get list of all apps present in steam along with their App IDs.
func (s *Steam) GetAppList() (*Apps, error) {
	res, err := http.Get(BaseURL + "/ISteamApps/GetAppList/v2?format=json")
	if err != nil {
		return nil, err
	}

	defer res.Body.Close()
	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	apps := new(Apps)
	err = json.Unmarshal(data, &apps)
	if err != nil {
		return nil, err
	}

	return apps, nil
}
<|endoftext|>


<commit_before>package main

import (
    "os"
    "fmt"
    "bufio"
    "regexp"
    "strings"
    "time"
    "net/url"
    "flag"
    "errors"
)

type singleUrlsList []Url;
var tempUrls singleUrlsList;

var Usage = func() {
    fmt.Println("Yata");
}

func (u *singleUrlsList) String() string {
    return fmt.Sprint(*u);
}

func (u *singleUrlsList) Set(singleUrl string) error {
    if (!urlExists(singleUrl)) {
        parsedUrl, err := parseUrl(singleUrl);

        if (err != nil) {
            return err;
        } else {
            *u = append(*u, parsedUrl);
        }
    } else {
        return errors.New("Duplicated Url: "+singleUrl);
    }

    return nil;
}

func (u *urlsList) String() string {
    return fmt.Sprint(*u);
}

func (u *urlsList) Set(file string) error {
    urlFile, err = os.Open(file);

    if (err != nil) {
        return errors.New("Error opening file: " + err.Error());
    }

    defer urlFile.Close();

    scanner := bufio.NewScanner(urlFile)

    for scanner.Scan() {
        url := scanner.Text();
        if (!urlExists(url)) {
            parsedUrl, err := parseUrl(url);

            if (err != nil) {
                return err;
            } else {
                *u = append(*u, parsedUrl);
            }
        }
    }

    return nil;
}

func (c *cookiesList) String() string {
    return fmt.Sprint(*c);
}

func (c *cookiesList) Set(cookie string) error {
    cookie = strings.Trim(cookie, "\"' ");

    *c = append(*c, cookie);

    return nil;
}

func (h *headersList) String() string {
    return fmt.Sprint(*h);
}

func (h *headersList) Set(header string) error {
    parts := strings.Split(header, ":");

    if (len(parts) != 2) {
        return errors.New("Wrong header format. Example: 'accept-encoding: gzip, deflate'");
    }

    key := strings.Trim(parts[0], "\"' ");
    value := strings.Trim(parts[1], "\"' ");

    (*h)[key] = value;

    return nil;
}

func (p *proxyURL) String() string {
    return fmt.Sprint(*p);
}

func (p *proxyURL) Set(enteredUrl string) error {
    enteredUrl = strings.Trim(enteredUrl, "\" ");

    var validArg = regexp.MustCompile("^localhost");

    if (enteredUrl == "localhost" || validArg.MatchString(enteredUrl)) {
        enteredUrl = "http://" + enteredUrl;
    }

    tempProxy, err := url.Parse(enteredUrl);

    if (err != nil) {
        return errors.New("Wrong proxy format. Example: http://localhost:8441");
    }

    if (tempProxy.Scheme == "") {
        tempProxy.Scheme = "http";
    }

    *p = proxyURL(tempProxy.String());

    return nil;
}

func init() {
    // Make HTTP Custom headers map
    headers = make(headersList);

    // Number of concurrent requests
    defaultUsage := "The number of concurrent requests (Default is 1)";
    flag.IntVar(&concurrent, "concurrent", 1, defaultUsage);
    flag.IntVar(&concurrent, "c", 1, defaultUsage + " - Shorthand");

    // Number of total requests to be sent
    defaultUsage = "The number of total requests to send (Default is 1)";
    flag.IntVar(&requests, "requests", 1, defaultUsage);
    flag.IntVar(&requests, "r", 1, defaultUsage + " - Shorthand");

    // To be verbose or not to be
    defaultUsage = "Verbosity (Default is False)";
    flag.BoolVar(&verbose, "verbose", false, defaultUsage);
    flag.BoolVar(&verbose, "v", false, defaultUsage + " - Shorthand");

    // To be verbose or not to be
    defaultUsage = "Prevents re-use of TCP connections (Default is False)";
    flag.BoolVar(&disableKeepAlive, "disable-keep-alive", false, defaultUsage);
    flag.BoolVar(&disableKeepAlive, "d", false, defaultUsage + " - Shorthand");

    // Random interval
    defaultUsage = "A random interval in seconds between 0 and the defined number (Default is 0)";
    flag.IntVar(&delay, "delay", 0, defaultUsage);
    flag.IntVar(&delay, "de", 0, defaultUsage + " - Shorthand");

    // Username for basic HTTP Authentication
    defaultUsage = "Username for basic HTTP Authentication";
    flag.StringVar(&basicAuthUsername, "username", "", defaultUsage);
    flag.StringVar(&basicAuthUsername, "user", "", defaultUsage + " - Shorthand");

    // Password for basic HTTP Authentication
    defaultUsage = "Password for basic HTTP Authentication";
    flag.StringVar(&basicAuthPassword, "password", "", defaultUsage);
    flag.StringVar(&basicAuthPassword, "pass", "", defaultUsage + " - Shorthand");

    // Response header timeout
    var tempResponseTimeout int;
    defaultUsage = "Specifies the amount of time to wait for a server's response headers (Default is 0 which means no timeout)";
    flag.IntVar(&tempResponseTimeout, "response-timeout", 0, defaultUsage);
    flag.IntVar(&tempResponseTimeout, "t", 0, defaultUsage + " - Shorthand");
    responseTimeout = time.Duration(tempResponseTimeout) * time.Second;

    // Connection timeout
    var tempConnectionTimeout int;
    defaultUsage = "Specifies the amount of time to wait for establishment of connection (Default is 0 which means no timeout)";
    flag.IntVar(&tempConnectionTimeout, "connection-timeout", 0, defaultUsage);
    flag.IntVar(&tempConnectionTimeout, "ct", 0, defaultUsage + " - Shorthand");
    connectionTimeout = time.Duration(tempConnectionTimeout) * time.Second;

    // Benchmarking url file
    defaultUsage = "Address of file containing urls to benchmark. This field is repeatable.";
    flag.Var(&urls, "file", defaultUsage);
    flag.Var(&urls, "f", defaultUsage + " - Shorthand");

    // Single URL to benchmark
    defaultUsage = "Single URL to benchmark. This field is repeatable.";
    flag.Var(&tempUrls, "url", defaultUsage);
    flag.Var(&tempUrls, "u", defaultUsage + " - Shorthand");

    // Custome cookies
    defaultUsage = "Custom cookies. This field is repeatable.";
    flag.Var(&cookies, "cookie", defaultUsage);
    flag.Var(&cookies, "co", defaultUsage + " - Shorthand");

    // Custom Headers
    defaultUsage = "Additional header information to send. This field is repeatable.";
    flag.Var(&headers, "header", defaultUsage);
    flag.Var(&headers, "he", defaultUsage + " - Shorthand");

    // HTTP proxy
    defaultUsage = "Proxy server to use.";
    flag.Var(&proxyUrl, "proxy", defaultUsage);
    flag.Var(&proxyUrl, "p", defaultUsage + " - Shorthand");

    flag.Usage = func() {
        flagDefaults();
    }

    flag.Parse();

    for _, singleUrl := range tempUrls {
        urls = append(urls, singleUrl);
    }

    if (requests == 0 || concurrent == 0 || requests < concurrent || len(urls) == 0) {
        flagDefaults();
        os.Exit(1);
    }
}

func flagDefaults () {
    fmt.Fprintf(os.Stderr, "\nUsage of gbnech:\n");
    flag.VisitAll(func(f *flag.Flag) {
        fmt.Printf("-%v: %v\n", f.Name, f.Usage);
    });

    fmt.Println("\nURL format should be as follow:");
    fmt.Println("METHOD|URL|POSTDATA or METHOD|URL");
    fmt.Println("Sample URLs: GET|www.google.com?search=test or POST|www.google.com|search=test or HEAD|www.google.com");
    fmt.Println("\nExamples:");
    fmt.Println("gbench -file ~/benchmarkurl.txt -r 100 -c 10 -v");
    fmt.Println("gbench -url www.google.com -url www.yahoo.com -r 100 -c 10 -v");
}

func parseUrl(enteredUrl string) (details Url, parseErr error) {

    enteredUrl = strings.Trim(enteredUrl, "\" ");
    parts := strings.Split(enteredUrl, "|");

    if ((len(parts) != 2 && len(parts) != 3) || (strings.ToUpper(parts[0]) != "GET" && strings.ToUpper(parts[0]) != "POST" && strings.ToUpper(parts[0]) != "HEAD")) {
        parseErr = errors.New("Wrong URL format. Example: GET|www.google.com?search=test or POST|www.google.com|search=test or HEAD|www.google.com");
    } else {

        details.method = strings.ToUpper(parts[0]);

        urlStruct, err := url.Parse(parts[1]);

        if (err != nil) {
            parseErr = errors.New("Wrong URL format: " + err.Error());
        } else {
            if (urlStruct.Scheme == "") {
                urlStruct.Scheme = "http";
            }

            details.url = urlStruct.String();

            if (details.method == "POST") {
                if (len(parts) == 3) {
                    details.data = make(map[string]string);
                    dataParts := strings.Split(parts[2], "&");

                    for i := 0; i < len(dataParts); i++ {
                        keyValue := strings.Split(dataParts[i], "=");
                        details.data[keyValue[0]] = keyValue[1];
                    }
                } else {
                    parseErr = errors.New("Wrong URL format. You need to provide post data. Example: POST|www.google.com|name=sasan&lastname=rose");
                }
            }
        }
    }

    return details, parseErr;
}

func urlExists(url string) bool {
    for _, u := range urls {
        if (url == u.url) {
            return true;
        }
    }

    return false;
}
<commit_msg>Examples updated<commit_after>package main

import (
    "os"
    "fmt"
    "bufio"
    "regexp"
    "strings"
    "time"
    "net/url"
    "flag"
    "errors"
)

type singleUrlsList []Url;
var tempUrls singleUrlsList;

var Usage = func() {
    fmt.Println("Yata");
}

func (u *singleUrlsList) String() string {
    return fmt.Sprint(*u);
}

func (u *singleUrlsList) Set(singleUrl string) error {
    if (!urlExists(singleUrl)) {
        parsedUrl, err := parseUrl(singleUrl);

        if (err != nil) {
            return err;
        } else {
            *u = append(*u, parsedUrl);
        }
    } else {
        return errors.New("Duplicated Url: "+singleUrl);
    }

    return nil;
}

func (u *urlsList) String() string {
    return fmt.Sprint(*u);
}

func (u *urlsList) Set(file string) error {
    urlFile, err = os.Open(file);

    if (err != nil) {
        return errors.New("Error opening file: " + err.Error());
    }

    defer urlFile.Close();

    scanner := bufio.NewScanner(urlFile)

    for scanner.Scan() {
        url := scanner.Text();
        if (!urlExists(url)) {
            parsedUrl, err := parseUrl(url);

            if (err != nil) {
                return err;
            } else {
                *u = append(*u, parsedUrl);
            }
        }
    }

    return nil;
}

func (c *cookiesList) String() string {
    return fmt.Sprint(*c);
}

func (c *cookiesList) Set(cookie string) error {
    cookie = strings.Trim(cookie, "\"' ");

    *c = append(*c, cookie);

    return nil;
}

func (h *headersList) String() string {
    return fmt.Sprint(*h);
}

func (h *headersList) Set(header string) error {
    parts := strings.Split(header, ":");

    if (len(parts) != 2) {
        return errors.New("Wrong header format. Example: 'accept-encoding: gzip, deflate'");
    }

    key := strings.Trim(parts[0], "\"' ");
    value := strings.Trim(parts[1], "\"' ");

    (*h)[key] = value;

    return nil;
}

func (p *proxyURL) String() string {
    return fmt.Sprint(*p);
}

func (p *proxyURL) Set(enteredUrl string) error {
    enteredUrl = strings.Trim(enteredUrl, "\" ");

    var validArg = regexp.MustCompile("^localhost");

    if (enteredUrl == "localhost" || validArg.MatchString(enteredUrl)) {
        enteredUrl = "http://" + enteredUrl;
    }

    tempProxy, err := url.Parse(enteredUrl);

    if (err != nil) {
        return errors.New("Wrong proxy format. Example: http://localhost:8441");
    }

    if (tempProxy.Scheme == "") {
        tempProxy.Scheme = "http";
    }

    *p = proxyURL(tempProxy.String());

    return nil;
}

func init() {
    // Make HTTP Custom headers map
    headers = make(headersList);

    // Number of concurrent requests
    defaultUsage := "The number of concurrent requests (Default is 1)";
    flag.IntVar(&concurrent, "concurrent", 1, defaultUsage);
    flag.IntVar(&concurrent, "c", 1, defaultUsage + " - Shorthand");

    // Number of total requests to be sent
    defaultUsage = "The number of total requests to send (Default is 1)";
    flag.IntVar(&requests, "requests", 1, defaultUsage);
    flag.IntVar(&requests, "r", 1, defaultUsage + " - Shorthand");

    // To be verbose or not to be
    defaultUsage = "Verbosity (Default is False)";
    flag.BoolVar(&verbose, "verbose", false, defaultUsage);
    flag.BoolVar(&verbose, "v", false, defaultUsage + " - Shorthand");

    // To be verbose or not to be
    defaultUsage = "Prevents re-use of TCP connections (Default is False)";
    flag.BoolVar(&disableKeepAlive, "disable-keep-alive", false, defaultUsage);
    flag.BoolVar(&disableKeepAlive, "d", false, defaultUsage + " - Shorthand");

    // Random interval
    defaultUsage = "A random interval in seconds between 0 and the defined number (Default is 0)";
    flag.IntVar(&delay, "delay", 0, defaultUsage);
    flag.IntVar(&delay, "de", 0, defaultUsage + " - Shorthand");

    // Username for basic HTTP Authentication
    defaultUsage = "Username for basic HTTP Authentication";
    flag.StringVar(&basicAuthUsername, "username", "", defaultUsage);
    flag.StringVar(&basicAuthUsername, "user", "", defaultUsage + " - Shorthand");

    // Password for basic HTTP Authentication
    defaultUsage = "Password for basic HTTP Authentication";
    flag.StringVar(&basicAuthPassword, "password", "", defaultUsage);
    flag.StringVar(&basicAuthPassword, "pass", "", defaultUsage + " - Shorthand");

    // Response header timeout
    var tempResponseTimeout int;
    defaultUsage = "Specifies the amount of time to wait for a server's response headers (Default is 0 which means no timeout)";
    flag.IntVar(&tempResponseTimeout, "response-timeout", 0, defaultUsage);
    flag.IntVar(&tempResponseTimeout, "t", 0, defaultUsage + " - Shorthand");
    responseTimeout = time.Duration(tempResponseTimeout) * time.Second;

    // Connection timeout
    var tempConnectionTimeout int;
    defaultUsage = "Specifies the amount of time to wait for establishment of connection (Default is 0 which means no timeout)";
    flag.IntVar(&tempConnectionTimeout, "connection-timeout", 0, defaultUsage);
    flag.IntVar(&tempConnectionTimeout, "ct", 0, defaultUsage + " - Shorthand");
    connectionTimeout = time.Duration(tempConnectionTimeout) * time.Second;

    // Benchmarking url file
    defaultUsage = "Address of file containing urls to benchmark. This field is repeatable.";
    flag.Var(&urls, "file", defaultUsage);
    flag.Var(&urls, "f", defaultUsage + " - Shorthand");

    // Single URL to benchmark
    defaultUsage = "Single URL to benchmark. This field is repeatable.";
    flag.Var(&tempUrls, "url", defaultUsage);
    flag.Var(&tempUrls, "u", defaultUsage + " - Shorthand");

    // Custome cookies
    defaultUsage = "Custom cookies. This field is repeatable.";
    flag.Var(&cookies, "cookie", defaultUsage);
    flag.Var(&cookies, "co", defaultUsage + " - Shorthand");

    // Custom Headers
    defaultUsage = "Additional header information to send. This field is repeatable.";
    flag.Var(&headers, "header", defaultUsage);
    flag.Var(&headers, "he", defaultUsage + " - Shorthand");

    // HTTP proxy
    defaultUsage = "Proxy server to use.";
    flag.Var(&proxyUrl, "proxy", defaultUsage);
    flag.Var(&proxyUrl, "p", defaultUsage + " - Shorthand");

    flag.Usage = func() {
        flagDefaults();
    }

    flag.Parse();

    for _, singleUrl := range tempUrls {
        urls = append(urls, singleUrl);
    }

    if (requests == 0 || concurrent == 0 || requests < concurrent || len(urls) == 0) {
        flagDefaults();
        os.Exit(1);
    }
}

func flagDefaults () {
    fmt.Fprintf(os.Stderr, "\nUsage of gbnech:\n");
    flag.VisitAll(func(f *flag.Flag) {
        fmt.Printf("-%v: %v\n", f.Name, f.Usage);
    });

    fmt.Println("\nURL format should be as follow:");
    fmt.Println("METHOD|URL|POSTDATA or METHOD|URL");
    fmt.Println("Sample URLs: GET|www.google.com?search=test or POST|www.google.com|search=test or HEAD|www.google.com");
    fmt.Println("\nExamples:");
    fmt.Println("gbench -file ~/benchmarkurl.txt -r 100 -c 10 -v");
    fmt.Println("gbench -url 'GET|www.google.com' -url 'GET|www.yahoo.com' -r 100 -c 10 -v");
}

func parseUrl(enteredUrl string) (details Url, parseErr error) {

    enteredUrl = strings.Trim(enteredUrl, "\" ");
    parts := strings.Split(enteredUrl, "|");

    if ((len(parts) != 2 && len(parts) != 3) || (strings.ToUpper(parts[0]) != "GET" && strings.ToUpper(parts[0]) != "POST" && strings.ToUpper(parts[0]) != "HEAD")) {
        parseErr = errors.New("Wrong URL format. Example: GET|www.google.com?search=test or POST|www.google.com|search=test or HEAD|www.google.com");
    } else {

        details.method = strings.ToUpper(parts[0]);

        urlStruct, err := url.Parse(parts[1]);

        if (err != nil) {
            parseErr = errors.New("Wrong URL format: " + err.Error());
        } else {
            if (urlStruct.Scheme == "") {
                urlStruct.Scheme = "http";
            }

            details.url = urlStruct.String();

            if (details.method == "POST") {
                if (len(parts) == 3) {
                    details.data = make(map[string]string);
                    dataParts := strings.Split(parts[2], "&");

                    for i := 0; i < len(dataParts); i++ {
                        keyValue := strings.Split(dataParts[i], "=");
                        details.data[keyValue[0]] = keyValue[1];
                    }
                } else {
                    parseErr = errors.New("Wrong URL format. You need to provide post data. Example: POST|www.google.com|name=sasan&lastname=rose");
                }
            }
        }
    }

    return details, parseErr;
}

func urlExists(url string) bool {
    for _, u := range urls {
        if (url == u.url) {
            return true;
        }
    }

    return false;
}
<|endoftext|>