<commit_before>package context

import (
	"fmt"
	"github.com/huangjunwen/JustSQL/utils"
	"github.com/pingcap/tidb/mysql"
	ts "github.com/pingcap/tidb/util/types"
	"path"
	"strings"
)

// TypeName represents a Go type in literal.
type TypeName struct {
	// Full import path, empty if it's builtin or in current module
	PkgPath string
	// Name for the package and type.
	PkgName  string
	TypeName string
}

// Return "PkgName.TypeName"
func (n *TypeName) String() string {
	if n.PkgName == "" {
		return n.TypeName
	}
	return fmt.Sprintf("%s.%s", n.PkgName, n.TypeName)
}

// Type associated information.
type TypeContext struct {
	// Map pkg path <-> pkg name
	pkgPath2Name map[string]string
	name2PkgPath map[string]string

	// ts.TypeToStr(*ts.FieldType.Tp) -> TypeName
	overrideAdaptTypes map[string]*TypeName
}

func NewTypeContext() *TypeContext {
	return &TypeContext{
		pkgPath2Name:       make(map[string]string),
		name2PkgPath:       make(map[string]string),
		overrideAdaptTypes: make(map[string]*TypeName),
	}
}

// Add and get a unique package name from its path.
func (tctx *TypeContext) AddPkg(pkg_path string) (string, error) {
	// Check exists.
	if name, ok := tctx.pkgPath2Name[pkg_path]; ok {
		return name, nil
	}
	// Special case for builtin.
	if pkg_path == "" {
		tctx.pkgPath2Name[""] = ""
		tctx.name2PkgPath[""] = ""
		return "", nil
	}
	// Try to use the base component as package name.
	base := path.Base(pkg_path)
	if !utils.IsIdent(base) {
		return "", fmt.Errorf("Bad package path: %q", pkg_path)
	}
	if _, ok := tctx.name2PkgPath[base]; !ok {
		tctx.pkgPath2Name[pkg_path] = base
		tctx.name2PkgPath[base] = pkg_path
		return base, nil
	}
	// Name conflict. Add a number suffix to resolve it.
	for i := 1; ; i += 1 {
		n := fmt.Sprintf("%s_%d", base, i)
		if _, ok := tctx.name2PkgPath[n]; !ok {
			tctx.pkgPath2Name[pkg_path] = n
			tctx.name2PkgPath[n] = pkg_path
			return n, nil
		}
	}
}

// Create TypeName from its package path and type name.
// Example:
//   tctx.CreateTypeName("sql", "NullString")
func (tctx *TypeContext) CreateTypeName(pkg_path, type_name string) (*TypeName, error) {
	if type_name == "" {
		return nil, fmt.Errorf("Missing type name")
	}

	pkg_name, err := tctx.AddPkg(pkg_path)
	if err != nil {
		return nil, err
	}

	return &TypeName{
		PkgPath:  pkg_path,
		PkgName:  pkg_name,
		TypeName: type_name,
	}, nil
}

// Create TypeName from colon-seperated spec:
//   [full_pkg_path:]type
// Example:
//   "[]byte"
//   "sql:NullString"
//   "github.com/go-sql-driver/mysql:NullTime"
func (tctx *TypeContext) CreateTypeNameFromSpec(s string) (*TypeName, error) {
	var pkg_path, type_name string
	i := strings.LastIndex(s, ":")
	if i < 0 {
		pkg_path = ""
		type_name = s
	} else {
		pkg_path = s[:i]
		type_name = s[i+1:]
	}

	return tctx.CreateTypeName(pkg_path, type_name)
}

// Override the adapt type for specific database type (tp_str).
// Example:
//   tn, err := tctx.CreateTypeName("github.com/go-sql-driver/mysql", "NullTime")
//   if err != nil {
//     ...
//   }
//   tctx.OverrideAdaptType("datetime", tn)
//   tctx.OverrideAdaptType("date", tn)
//   tctx.OverrideAdaptType("timestamp", tn)
func (tctx *TypeContext) OverrideAdaptType(tp_str string, tn *TypeName) error {
	tctx.overrideAdaptTypes[strings.ToLower(tp_str)] = tn
	return nil
}

// Change datetime/date/timestamp adapt type using 'mysql.NullTime' (generated code
// depends on "github.com/go-sql-driver/mysql")
func (tctx *TypeContext) UseMySQLNullTime() error {
	tn, err := tctx.CreateTypeName("github.com/go-sql-driver/mysql", "NullTime")
	if err != nil {
		return err
	}
	tctx.OverrideAdaptType("datetime", tn)
	tctx.OverrideAdaptType("date", tn)
	tctx.OverrideAdaptType("timestamp", tn)
	return nil
}

// Find a type suitable to store database field type.
func (tctx *TypeContext) AdaptType(ft *ts.FieldType) (*TypeName, error) {
	// see: github.com/pingcap/tidb/mysql/type.go and github.com/pingcap/tidb/util/types/field_type.go
	cls := ft.ToClass()
	tp := ft.Tp
	flen := ft.Flen
	flag := ft.Flag
	nullable := !mysql.HasNotNullFlag(flag)
	unsigned := mysql.HasUnsignedFlag(flag)
	binary := mysql.HasBinaryFlag(flag)

	if tn, ok := tctx.overrideAdaptTypes[strings.ToLower(ts.TypeToStr(ft.Tp, ft.Charset))]; ok {
		return tn, nil
	}

	switch cls {
	case ts.ClassInt:
		switch tp {
		case mysql.TypeBit: // bit
			if flen == 1 {
				if nullable {
					return tctx.CreateTypeName("sql", "NullBool")
				} else {
					return tctx.CreateTypeName("", "bool")
				}
			}

			if nullable {
				return tctx.CreateTypeName("sql", "NullInt64")
			}

			if flen <= 8 {
				return tctx.CreateTypeName("", "uint8")
			} else if flen <= 16 {
				return tctx.CreateTypeName("", "uint16")
			} else if flen <= 32 {
				return tctx.CreateTypeName("", "uint32")
			} else {
				return tctx.CreateTypeName("", "uint64")
			}

		case mysql.TypeTiny: // tinyint
			// tinyint(1) also means bool
			if flen == 1 {
				if nullable {
					return tctx.CreateTypeName("sql", "NullBool")
				} else {
					return tctx.CreateTypeName("", "bool")
				}
			}

			if nullable {
				return tctx.CreateTypeName("sql", "NullInt64")
			}

			if unsigned {
				return tctx.CreateTypeName("", "uint8")
			} else {
				return tctx.CreateTypeName("", "int8")
			}

		case mysql.TypeShort: // smallint
			if nullable {
				return tctx.CreateTypeName("sql", "NullInt64")
			}

			if unsigned {
				return tctx.CreateTypeName("", "uint16")
			} else {
				return tctx.CreateTypeName("", "int16")
			}

		case mysql.TypeInt24: // mediumint
			fallthrough

		case mysql.TypeLong: // int
			if nullable {
				return tctx.CreateTypeName("sql", "NullInt64")
			}

			if unsigned {
				return tctx.CreateTypeName("", "uint32")
			} else {
				return tctx.CreateTypeName("", "int32")
			}

		case mysql.TypeLonglong: // bigint
			if nullable {
				return tctx.CreateTypeName("sql", "NullInt64")
			}

			if unsigned {
				return tctx.CreateTypeName("", "uint64")
			} else {
				return tctx.CreateTypeName("", "int64")
			}

		case mysql.TypeYear:
			// 16-bit is enough for yyyy
			return tctx.CreateTypeName("", "uint16")
		}

	case ts.ClassReal:
		if nullable {
			return tctx.CreateTypeName("sql", "NullFloat64")
		}
		switch tp {
		case mysql.TypeFloat: // float
			return tctx.CreateTypeName("", "float32")
		case mysql.TypeDouble: // double
			return tctx.CreateTypeName("", "float64")
		}

	// NOTE: it is STRONGLY recommended to use precise type to store decimal.
	case ts.ClassDecimal:
		if nullable {
			return tctx.CreateTypeName("sql", "NullFloat64")
		}
		return tctx.CreateTypeName("", "float64")

	case ts.ClassString:
		if binary {
			return tctx.CreateTypeName("", "[]byte")
		}
		if nullable {
			return tctx.CreateTypeName("sql", "NullString")
		}
		return tctx.CreateTypeName("", "string")

	}

	return nil, fmt.Errorf("Unknown type %x", ft.Tp)
}
<commit_msg>Alter some comments.<commit_after>package context

import (
	"fmt"
	"github.com/huangjunwen/JustSQL/utils"
	"github.com/pingcap/tidb/mysql"
	ts "github.com/pingcap/tidb/util/types"
	"path"
	"strings"
)

// TypeName represents a Go type in literal.
type TypeName struct {
	// Full import path, empty if it's builtin or in current module
	PkgPath string
	// Name for the package and type.
	PkgName  string
	TypeName string
}

// Return "PkgName.TypeName"
func (n *TypeName) String() string {
	if n.PkgName == "" {
		return n.TypeName
	}
	return fmt.Sprintf("%s.%s", n.PkgName, n.TypeName)
}

// Type associated information.
type TypeContext struct {
	// Map pkg path <-> pkg name
	pkgPath2Name map[string]string
	name2PkgPath map[string]string

	// ts.TypeToStr(*ts.FieldType.Tp) -> TypeName
	overrideAdaptTypes map[string]*TypeName
}

func NewTypeContext() *TypeContext {
	return &TypeContext{
		pkgPath2Name:       make(map[string]string),
		name2PkgPath:       make(map[string]string),
		overrideAdaptTypes: make(map[string]*TypeName),
	}
}

// Add and get a unique package name from its path.
func (tctx *TypeContext) AddPkg(pkg_path string) (string, error) {
	// Check exists.
	if name, ok := tctx.pkgPath2Name[pkg_path]; ok {
		return name, nil
	}
	// Special case for builtin.
	if pkg_path == "" {
		tctx.pkgPath2Name[""] = ""
		tctx.name2PkgPath[""] = ""
		return "", nil
	}
	// Try to use the base component as package name.
	base := path.Base(pkg_path)
	if !utils.IsIdent(base) {
		return "", fmt.Errorf("Bad package path: %q", pkg_path)
	}
	if _, ok := tctx.name2PkgPath[base]; !ok {
		tctx.pkgPath2Name[pkg_path] = base
		tctx.name2PkgPath[base] = pkg_path
		return base, nil
	}
	// Name conflict. Add a number suffix to resolve it.
	for i := 1; ; i += 1 {
		n := fmt.Sprintf("%s_%d", base, i)
		if _, ok := tctx.name2PkgPath[n]; !ok {
			tctx.pkgPath2Name[pkg_path] = n
			tctx.name2PkgPath[n] = pkg_path
			return n, nil
		}
	}
}

// Create TypeName from its package path and type name.
// Example:
//   tctx.CreateTypeName("sql", "NullString")
func (tctx *TypeContext) CreateTypeName(pkg_path, type_name string) (*TypeName, error) {
	if type_name == "" {
		return nil, fmt.Errorf("Missing type name")
	}

	pkg_name, err := tctx.AddPkg(pkg_path)
	if err != nil {
		return nil, err
	}

	return &TypeName{
		PkgPath:  pkg_path,
		PkgName:  pkg_name,
		TypeName: type_name,
	}, nil
}

// Create TypeName from colon-seperated spec:
//   [full_pkg_path:]type
// Example:
//   "[]byte"
//   "sql:NullString"
//   "github.com/go-sql-driver/mysql:NullTime"
func (tctx *TypeContext) CreateTypeNameFromSpec(s string) (*TypeName, error) {
	var pkg_path, type_name string
	i := strings.LastIndex(s, ":")
	if i < 0 {
		pkg_path = ""
		type_name = s
	} else {
		pkg_path = s[:i]
		type_name = s[i+1:]
	}

	return tctx.CreateTypeName(pkg_path, type_name)
}

// Override the adapt type for specific database field type.
// Example:
//   tn, err := tctx.CreateTypeName("github.com/go-sql-driver/mysql", "NullTime")
//   if err != nil {
//     ...
//   }
//   tctx.OverrideAdaptType("datetime", tn)
//   tctx.OverrideAdaptType("date", tn)
//   tctx.OverrideAdaptType("timestamp", tn)
func (tctx *TypeContext) OverrideAdaptType(tp_str string, tn *TypeName) error {
	tctx.overrideAdaptTypes[strings.ToLower(tp_str)] = tn
	return nil
}

// Use 'mysql.NullTime' for datetime/date/timestamp field type (generated code
// depends on "github.com/go-sql-driver/mysql")
func (tctx *TypeContext) UseMySQLNullTime() error {
	tn, err := tctx.CreateTypeName("github.com/go-sql-driver/mysql", "NullTime")
	if err != nil {
		return err
	}
	tctx.OverrideAdaptType("datetime", tn)
	tctx.OverrideAdaptType("date", tn)
	tctx.OverrideAdaptType("timestamp", tn)
	return nil
}

// Main method of TypeContext. Find a type suitable to store database field type.
func (tctx *TypeContext) AdaptType(ft *ts.FieldType) (*TypeName, error) {
	// see: github.com/pingcap/tidb/mysql/type.go and github.com/pingcap/tidb/util/types/field_type.go
	cls := ft.ToClass()
	tp := ft.Tp
	flen := ft.Flen
	flag := ft.Flag
	nullable := !mysql.HasNotNullFlag(flag)
	unsigned := mysql.HasUnsignedFlag(flag)
	binary := mysql.HasBinaryFlag(flag)

	if tn, ok := tctx.overrideAdaptTypes[strings.ToLower(ts.TypeToStr(ft.Tp, ft.Charset))]; ok {
		return tn, nil
	}

	switch cls {
	case ts.ClassInt:
		switch tp {
		case mysql.TypeBit: // bit
			if flen == 1 {
				if nullable {
					return tctx.CreateTypeName("sql", "NullBool")
				} else {
					return tctx.CreateTypeName("", "bool")
				}
			}

			if nullable {
				return tctx.CreateTypeName("sql", "NullInt64")
			}

			if flen <= 8 {
				return tctx.CreateTypeName("", "uint8")
			} else if flen <= 16 {
				return tctx.CreateTypeName("", "uint16")
			} else if flen <= 32 {
				return tctx.CreateTypeName("", "uint32")
			} else {
				return tctx.CreateTypeName("", "uint64")
			}

		case mysql.TypeTiny: // tinyint
			// tinyint(1) also means bool
			if flen == 1 {
				if nullable {
					return tctx.CreateTypeName("sql", "NullBool")
				} else {
					return tctx.CreateTypeName("", "bool")
				}
			}

			if nullable {
				return tctx.CreateTypeName("sql", "NullInt64")
			}

			if unsigned {
				return tctx.CreateTypeName("", "uint8")
			} else {
				return tctx.CreateTypeName("", "int8")
			}

		case mysql.TypeShort: // smallint
			if nullable {
				return tctx.CreateTypeName("sql", "NullInt64")
			}

			if unsigned {
				return tctx.CreateTypeName("", "uint16")
			} else {
				return tctx.CreateTypeName("", "int16")
			}

		case mysql.TypeInt24: // mediumint
			fallthrough

		case mysql.TypeLong: // int
			if nullable {
				return tctx.CreateTypeName("sql", "NullInt64")
			}

			if unsigned {
				return tctx.CreateTypeName("", "uint32")
			} else {
				return tctx.CreateTypeName("", "int32")
			}

		case mysql.TypeLonglong: // bigint
			if nullable {
				return tctx.CreateTypeName("sql", "NullInt64")
			}

			if unsigned {
				return tctx.CreateTypeName("", "uint64")
			} else {
				return tctx.CreateTypeName("", "int64")
			}

		case mysql.TypeYear:
			// 16-bit is enough for yyyy
			return tctx.CreateTypeName("", "uint16")
		}

	case ts.ClassReal:
		if nullable {
			return tctx.CreateTypeName("sql", "NullFloat64")
		}
		switch tp {
		case mysql.TypeFloat: // float
			return tctx.CreateTypeName("", "float32")
		case mysql.TypeDouble: // double
			return tctx.CreateTypeName("", "float64")
		}

	// NOTE: it is STRONGLY recommended to use precise type to store decimal.
	case ts.ClassDecimal:
		if nullable {
			return tctx.CreateTypeName("sql", "NullFloat64")
		}
		return tctx.CreateTypeName("", "float64")

	case ts.ClassString:
		if binary {
			return tctx.CreateTypeName("", "[]byte")
		}
		if nullable {
			return tctx.CreateTypeName("sql", "NullString")
		}
		return tctx.CreateTypeName("", "string")

	}

	return nil, fmt.Errorf("Unknown type %x", ft.Tp)
}
<|endoftext|>


<commit_before>package echo

import (
	"encoding/xml"
	"html/template"
	"strconv"
	"sync"
)

var (
	mutex         sync.RWMutex
	emptyHTML     = template.HTML(``)
	emptyJS       = template.JS(``)
	emptyCSS      = template.CSS(``)
	emptyHTMLAttr = template.HTMLAttr(``)
)

type Store map[string]interface{}

func (s Store) Set(key string, value interface{}) Store {
	mutex.Lock()
	s[key] = value
	mutex.Unlock()
	return s
}

func (s Store) Get(key string, defaults ...interface{}) interface{} {
	mutex.RLock()
	defer mutex.RUnlock()
	if v, y := s[key]; y {
		if v == nil && len(defaults) > 0 {
			return defaults[0]
		}
		return v
	}
	if len(defaults) > 0 {
		return defaults[0]
	}
	return nil
}

func (s Store) String(key string, defaults ...interface{}) string {
	if v, y := s.Get(key, defaults...).(string); y {
		return v
	}
	return ``
}

func (s Store) HTML(key string, defaults ...interface{}) template.HTML {
	val := s.Get(key, defaults...)
	if v, y := val.(template.HTML); y {
		return v
	}
	if v, y := val.(string); y {
		return template.HTML(v)
	}
	return emptyHTML
}

func (s Store) HTMLAttr(key string, defaults ...interface{}) template.HTMLAttr {
	val := s.Get(key, defaults...)
	if v, y := val.(template.HTMLAttr); y {
		return v
	}
	if v, y := val.(string); y {
		return template.HTMLAttr(v)
	}
	return emptyHTMLAttr
}

func (s Store) JS(key string, defaults ...interface{}) template.JS {
	val := s.Get(key, defaults...)
	if v, y := val.(template.JS); y {
		return v
	}
	if v, y := val.(string); y {
		return template.JS(v)
	}
	return emptyJS
}

func (s Store) CSS(key string, defaults ...interface{}) template.CSS {
	val := s.Get(key, defaults...)
	if v, y := val.(template.CSS); y {
		return v
	}
	if v, y := val.(string); y {
		return template.CSS(v)
	}
	return emptyCSS
}

func (s Store) Bool(key string, defaults ...interface{}) bool {
	if v, y := s.Get(key, defaults...).(bool); y {
		return v
	}
	return false
}

func (s Store) Float64(key string, defaults ...interface{}) float64 {
	val := s.Get(key, defaults...)
	if v, y := val.(float64); y {
		return v
	}
	if v, y := val.(int64); y {
		return float64(v)
	}
	if v, y := val.(uint64); y {
		return float64(v)
	}
	if v, y := val.(float32); y {
		return float64(v)
	}
	if v, y := val.(int32); y {
		return float64(v)
	}
	if v, y := val.(uint32); y {
		return float64(v)
	}
	if v, y := val.(int); y {
		return float64(v)
	}
	if v, y := val.(uint); y {
		return float64(v)
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseFloat(v, 64)
		return v
	}
	return 0
}

func (s Store) Float32(key string, defaults ...interface{}) float32 {
	val := s.Get(key, defaults...)
	if v, y := val.(float32); y {
		return v
	}
	if v, y := val.(int32); y {
		return float32(v)
	}
	if v, y := val.(uint32); y {
		return float32(v)
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseFloat(v, 32)
		return float32(v)
	}
	return 0
}

func (s Store) Int8(key string, defaults ...interface{}) int8 {
	val := s.Get(key, defaults...)
	if v, y := val.(int8); y {
		return v
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseInt(v, 10, 8)
		return int8(v)
	}
	return 0
}

func (s Store) Int16(key string, defaults ...interface{}) int16 {
	val := s.Get(key, defaults...)
	if v, y := val.(int16); y {
		return v
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseInt(v, 10, 16)
		return int16(v)
	}
	return 0
}

func (s Store) Int(key string, defaults ...interface{}) int {
	val := s.Get(key, defaults...)
	if v, y := val.(int); y {
		return v
	}
	if v, y := val.(string); y {
		v, _ := strconv.Atoi(v)
		return v
	}
	return 0
}

func (s Store) Int32(key string, defaults ...interface{}) int32 {
	val := s.Get(key, defaults...)
	if v, y := val.(int32); y {
		return v
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseInt(v, 10, 32)
		return int32(v)
	}
	return 0
}

func (s Store) Int64(key string, defaults ...interface{}) int64 {
	val := s.Get(key, defaults...)
	if v, y := val.(int64); y {
		return v
	}
	if v, y := val.(int32); y {
		return int64(v)
	}
	if v, y := val.(uint32); y {
		return int64(v)
	}
	if v, y := val.(int); y {
		return int64(v)
	}
	if v, y := val.(uint); y {
		return int64(v)
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseInt(v, 10, 64)
		return v
	}
	return 0
}

func (s Store) Decr(key string, n int64, defaults ...interface{}) int64 {
	v, _ := s.Get(key, defaults...).(int64)
	v -= n
	s.Set(key, v)
	return v
}

func (s Store) Incr(key string, n int64, defaults ...interface{}) int64 {
	v, _ := s.Get(key, defaults...).(int64)
	v += n
	s.Set(key, v)
	return v
}

func (s Store) Uint8(key string, defaults ...interface{}) uint8 {
	val := s.Get(key, defaults...)
	if v, y := val.(uint8); y {
		return v
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseUint(v, 10, 8)
		return uint8(v)
	}
	return 0
}

func (s Store) Uint16(key string, defaults ...interface{}) uint16 {
	val := s.Get(key, defaults...)
	if v, y := val.(uint16); y {
		return v
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseUint(v, 10, 16)
		return uint16(v)
	}
	return 0
}

func (s Store) Uint(key string, defaults ...interface{}) uint {
	val := s.Get(key, defaults...)
	if v, y := val.(uint); y {
		return v
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseUint(v, 10, 32)
		return uint(v)
	}
	return 0
}

func (s Store) Uint32(key string, defaults ...interface{}) uint32 {
	val := s.Get(key, defaults...)
	if v, y := val.(uint32); y {
		return v
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseUint(v, 10, 32)
		return uint32(v)
	}
	return 0
}

func (s Store) Uint64(key string, defaults ...interface{}) uint64 {
	val := s.Get(key, defaults...)
	if v, y := val.(uint64); y {
		return v
	}
	if v, y := val.(string); y {
		v, _ := strconv.ParseUint(v, 10, 64)
		return v
	}
	return 0
}

func (s Store) Store(key string, defaults ...interface{}) Store {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case Store:
		return v
	case map[string]interface{}:
		return Store(v)
	case map[string]uint64:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]int64:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]uint:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]int:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]uint32:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]int32:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]float32:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]float64:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]string:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	default:
		return Store{}
	}
}

func (s Store) Delete(keys ...string) {
	mutex.Lock()
	for _, key := range keys {
		if _, y := s[key]; y {
			delete(s, key)
		}
	}
	mutex.Unlock()
}

// MarshalXML allows type Store to be used with xml.Marshal
func (s Store) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	if start.Name.Local == `Store` {
		start.Name.Local = `Map`
	}
	if err := e.EncodeToken(start); err != nil {
		return err
	}
	for key, value := range s {
		elem := xml.StartElement{
			Name: xml.Name{Space: ``, Local: key},
			Attr: []xml.Attr{},
		}
		if err := e.EncodeElement(value, elem); err != nil {
			return err
		}
	}
	return e.EncodeToken(xml.EndElement{Name: start.Name})
}

// ToData conversion to *RawData
func (s Store) ToData() *RawData {
	var info, zone, data interface{}
	if v, y := s["Data"]; y {
		data = v
	}
	if v, y := s["Zone"]; y {
		zone = v
	}
	if v, y := s["Info"]; y {
		info = v
	}
	var code State
	if v, y := s["Code"]; y {
		if c, y := v.(int); y {
			code = State(c)
		} else if c, y := v.(State); y {
			code = c
		}
	}
	return &RawData{
		Code: code,
		Info: info,
		Zone: zone,
		Data: data,
	}
}

func (s Store) DeepMerge(source Store) {
	for k, value := range source {
		var (
			destValue interface{}
			ok        bool
		)
		if destValue, ok = s[k]; !ok {
			s[k] = value
			continue
		}
		sourceM, sourceOk := value.(H)
		destM, destOk := destValue.(H)
		if sourceOk && sourceOk == destOk {
			destM.DeepMerge(sourceM)
		} else {
			s[k] = value
		}
	}
}

func (s Store) Clone() Store {
	r := make(Store)
	for k, value := range s {
		switch v := value.(type) {
		case Store:
			r[k] = v.Clone()
		case []Store:
			vCopy := make([]Store, len(v))
			for i, row := range v {
				vCopy[i] = row.Clone()
			}
			r[k] = vCopy
		default:
			r[k] = value
		}
	}
	return r
}
<commit_msg>improved<commit_after>package echo

import (
	"encoding/xml"
	"fmt"
	"html/template"
	"strconv"
	"sync"
)

var (
	mutex         sync.RWMutex
	emptyHTML     = template.HTML(``)
	emptyJS       = template.JS(``)
	emptyCSS      = template.CSS(``)
	emptyHTMLAttr = template.HTMLAttr(``)
)

type Store map[string]interface{}

func (s Store) Set(key string, value interface{}) Store {
	mutex.Lock()
	s[key] = value
	mutex.Unlock()
	return s
}

func (s Store) Get(key string, defaults ...interface{}) interface{} {
	mutex.RLock()
	defer mutex.RUnlock()
	if v, y := s[key]; y {
		if v == nil && len(defaults) > 0 {
			return defaults[0]
		}
		return v
	}
	if len(defaults) > 0 {
		return defaults[0]
	}
	return nil
}

func (s Store) String(key string, defaults ...interface{}) string {
	if v, y := s.Get(key, defaults...).(string); y {
		return v
	}
	return ``
}

func (s Store) HTML(key string, defaults ...interface{}) template.HTML {
	val := s.Get(key, defaults...)
	if v, y := val.(template.HTML); y {
		return v
	}
	if v, y := val.(string); y {
		return template.HTML(v)
	}
	return emptyHTML
}

func (s Store) HTMLAttr(key string, defaults ...interface{}) template.HTMLAttr {
	val := s.Get(key, defaults...)
	if v, y := val.(template.HTMLAttr); y {
		return v
	}
	if v, y := val.(string); y {
		return template.HTMLAttr(v)
	}
	return emptyHTMLAttr
}

func (s Store) JS(key string, defaults ...interface{}) template.JS {
	val := s.Get(key, defaults...)
	if v, y := val.(template.JS); y {
		return v
	}
	if v, y := val.(string); y {
		return template.JS(v)
	}
	return emptyJS
}

func (s Store) CSS(key string, defaults ...interface{}) template.CSS {
	val := s.Get(key, defaults...)
	if v, y := val.(template.CSS); y {
		return v
	}
	if v, y := val.(string); y {
		return template.CSS(v)
	}
	return emptyCSS
}

func (s Store) Bool(key string, defaults ...interface{}) bool {
	if v, y := s.Get(key, defaults...).(bool); y {
		return v
	}
	return false
}

func (s Store) Float64(key string, defaults ...interface{}) float64 {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case float64:
		return v
	case int64:
		return float64(v)
	case uint64:
		return float64(v)
	case float32:
		return float64(v)
	case int32:
		return float64(v)
	case uint32:
		return float64(v)
	case int:
		return float64(v)
	case uint:
		return float64(v)
	case string:
		i, _ := strconv.ParseFloat(v, 64)
		return i
	default:
		s := fmt.Sprint(v)
		i, _ := strconv.ParseFloat(s, 64)
		return i
	}
}

func (s Store) Float32(key string, defaults ...interface{}) float32 {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case float32:
		return v
	case int32:
		return float32(v)
	case uint32:
		return float32(v)
	case string:
		f, _ := strconv.ParseFloat(v, 32)
		return float32(f)
	default:
		s := fmt.Sprint(val)
		f, _ := strconv.ParseFloat(s, 32)
		return float32(f)
	}
}

func (s Store) Int8(key string, defaults ...interface{}) int8 {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case int8:
		return v
	case string:
		i, _ := strconv.ParseInt(v, 10, 8)
		return int8(i)
	default:
		s := fmt.Sprint(val)
		i, _ := strconv.ParseInt(s, 10, 8)
		return int8(i)
	}
}

func (s Store) Int16(key string, defaults ...interface{}) int16 {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case int16:
		return v
	case string:
		i, _ := strconv.ParseInt(v, 10, 16)
		return int16(i)
	default:
		s := fmt.Sprint(v)
		i, _ := strconv.ParseInt(s, 10, 16)
		return int16(i)
	}
}

func (s Store) Int(key string, defaults ...interface{}) int {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case int:
		return v
	case string:
		i, _ := strconv.Atoi(v)
		return i
	default:
		s := fmt.Sprint(v)
		i, _ := strconv.Atoi(s)
		return i
	}
}

func (s Store) Int32(key string, defaults ...interface{}) int32 {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case int32:
		return v
	case string:
		i, _ := strconv.ParseInt(v, 10, 32)
		return int32(i)
	default:
		s := fmt.Sprint(v)
		i, _ := strconv.ParseInt(s, 10, 32)
		return int32(i)
	}
}

func (s Store) Int64(key string, defaults ...interface{}) int64 {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case int64:
		return v
	case int32:
		return int64(v)
	case uint32:
		return int64(v)
	case int:
		return int64(v)
	case uint:
		return int64(v)
	case string:
		i, _ := strconv.ParseInt(v, 10, 64)
		return i
	default:
		s := fmt.Sprint(v)
		i, _ := strconv.ParseInt(s, 10, 64)
		return i
	}
}

func (s Store) Decr(key string, n int64, defaults ...interface{}) int64 {
	v, _ := s.Get(key, defaults...).(int64)
	v -= n
	s.Set(key, v)
	return v
}

func (s Store) Incr(key string, n int64, defaults ...interface{}) int64 {
	v, _ := s.Get(key, defaults...).(int64)
	v += n
	s.Set(key, v)
	return v
}

func (s Store) Uint8(key string, defaults ...interface{}) uint8 {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case uint8:
		return v
	case string:
		i, _ := strconv.ParseUint(v, 10, 8)
		return uint8(i)
	default:
		s := fmt.Sprint(v)
		i, _ := strconv.ParseUint(s, 10, 8)
		return uint8(i)
	}
}

func (s Store) Uint16(key string, defaults ...interface{}) uint16 {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case uint16:
		return v
	case string:
		i, _ := strconv.ParseUint(v, 10, 16)
		return uint16(i)
	default:
		s := fmt.Sprint(v)
		i, _ := strconv.ParseUint(s, 10, 16)
		return uint16(i)
	}
}

func (s Store) Uint(key string, defaults ...interface{}) uint {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case uint:
		return v
	case string:
		i, _ := strconv.ParseUint(v, 10, 32)
		return uint(i)
	default:
		s := fmt.Sprint(v)
		i, _ := strconv.ParseUint(s, 10, 32)
		return uint(i)
	}
}

func (s Store) Uint32(key string, defaults ...interface{}) uint32 {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case uint32:
		return v
	case string:
		i, _ := strconv.ParseUint(v, 10, 32)
		return uint32(i)
	default:
		s := fmt.Sprint(v)
		i, _ := strconv.ParseUint(s, 10, 32)
		return uint32(i)
	}
}

func (s Store) Uint64(key string, defaults ...interface{}) uint64 {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case uint64:
		return v
	case string:
		i, _ := strconv.ParseUint(v, 10, 64)
		return i
	default:
		s := fmt.Sprint(v)
		i, _ := strconv.ParseUint(s, 10, 64)
		return i
	}
}

func (s Store) Store(key string, defaults ...interface{}) Store {
	val := s.Get(key, defaults...)
	switch v := val.(type) {
	case Store:
		return v
	case map[string]interface{}:
		return Store(v)
	case map[string]uint64:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]int64:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]uint:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]int:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]uint32:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]int32:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]float32:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]float64:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	case map[string]string:
		r := Store{}
		for k, a := range v {
			r[k] = interface{}(a)
		}
		return r
	default:
		return Store{}
	}
}

func (s Store) Delete(keys ...string) {
	mutex.Lock()
	for _, key := range keys {
		if _, y := s[key]; y {
			delete(s, key)
		}
	}
	mutex.Unlock()
}

// MarshalXML allows type Store to be used with xml.Marshal
func (s Store) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	if start.Name.Local == `Store` {
		start.Name.Local = `Map`
	}
	if err := e.EncodeToken(start); err != nil {
		return err
	}
	for key, value := range s {
		elem := xml.StartElement{
			Name: xml.Name{Space: ``, Local: key},
			Attr: []xml.Attr{},
		}
		if err := e.EncodeElement(value, elem); err != nil {
			return err
		}
	}
	return e.EncodeToken(xml.EndElement{Name: start.Name})
}

// ToData conversion to *RawData
func (s Store) ToData() *RawData {
	var info, zone, data interface{}
	if v, y := s["Data"]; y {
		data = v
	}
	if v, y := s["Zone"]; y {
		zone = v
	}
	if v, y := s["Info"]; y {
		info = v
	}
	var code State
	if v, y := s["Code"]; y {
		if c, y := v.(int); y {
			code = State(c)
		} else if c, y := v.(State); y {
			code = c
		}
	}
	return &RawData{
		Code: code,
		Info: info,
		Zone: zone,
		Data: data,
	}
}

func (s Store) DeepMerge(source Store) {
	for k, value := range source {
		var (
			destValue interface{}
			ok        bool
		)
		if destValue, ok = s[k]; !ok {
			s[k] = value
			continue
		}
		sourceM, sourceOk := value.(H)
		destM, destOk := destValue.(H)
		if sourceOk && sourceOk == destOk {
			destM.DeepMerge(sourceM)
		} else {
			s[k] = value
		}
	}
}

func (s Store) Clone() Store {
	r := make(Store)
	for k, value := range s {
		switch v := value.(type) {
		case Store:
			r[k] = v.Clone()
		case []Store:
			vCopy := make([]Store, len(v))
			for i, row := range v {
				vCopy[i] = row.Clone()
			}
			r[k] = vCopy
		default:
			r[k] = value
		}
	}
	return r
}
<|endoftext|>


<commit_before>// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package models

import (
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"testing"
	"time"

	"code.gitea.io/gitea/modules/setting"

	"github.com/Unknwon/com"
	"github.com/go-xorm/core"
	"github.com/go-xorm/xorm"
	"github.com/stretchr/testify/assert"
	"gopkg.in/testfixtures.v2"
)

// NonexistentID an ID that will never exist
const NonexistentID = 9223372036854775807

// giteaRoot a path to the gitea root
var giteaRoot string

func fatalTestError(fmtStr string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, fmtStr, args...)
	os.Exit(1)
}

// MainTest a reusable TestMain(..) function for unit tests that need to use a
// test database. Creates the test database, and sets necessary settings.
func MainTest(m *testing.M, pathToGiteaRoot string) {
	var err error
	giteaRoot = pathToGiteaRoot
	fixturesDir := filepath.Join(pathToGiteaRoot, "models", "fixtures")
	if err = createTestEngine(fixturesDir); err != nil {
		fatalTestError("Error creating test engine: %v\n", err)
	}

	setting.AppURL = "https://try.gitea.io/"
	setting.RunUser = "runuser"
	setting.SSH.Port = 3000
	setting.SSH.Domain = "try.gitea.io"
	setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos")
	if err != nil {
		fatalTestError("TempDir: %v\n", err)
	}
	setting.AppDataPath, err = ioutil.TempDir(os.TempDir(), "appdata")
	if err != nil {
		fatalTestError("TempDir: %v\n", err)
	}
	setting.AppWorkPath = pathToGiteaRoot
	setting.StaticRootPath = pathToGiteaRoot
	setting.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/")
	if err != nil {
		fatalTestError("url.Parse: %v\n", err)
	}

	exitStatus := m.Run()
	if err = removeAllWithRetry(setting.RepoRootPath); err != nil {
		fatalTestError("os.RemoveAll: %v\n", err)
	}
	if err = removeAllWithRetry(setting.AppDataPath); err != nil {
		fatalTestError("os.RemoveAll: %v\n", err)
	}
	os.Exit(exitStatus)
}

func createTestEngine(fixturesDir string) error {
	var err error
	x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
	if err != nil {
		return err
	}
	x.SetMapper(core.GonicMapper{})
	if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
		return err
	}
	switch os.Getenv("GITEA_UNIT_TESTS_VERBOSE") {
	case "true", "1":
		x.ShowSQL(true)
	}

	return InitFixtures(&testfixtures.SQLite{}, fixturesDir)
}

func removeAllWithRetry(dir string) error {
	var err error
	for i := 0; i < 20; i++ {
		err = os.RemoveAll(dir)
		if err == nil {
			break
		}
		time.Sleep(100 * time.Millisecond)
	}
	return err
}

// PrepareTestDatabase load test fixtures into test database
func PrepareTestDatabase() error {
	return LoadFixtures()
}

// PrepareTestEnv prepares the environment for unit tests. Can only be called
// by tests that use the above MainTest(..) function.
func PrepareTestEnv(t testing.TB) {
	assert.NoError(t, PrepareTestDatabase())
	assert.NoError(t, removeAllWithRetry(setting.RepoRootPath))
	metaPath := filepath.Join(giteaRoot, "integrations", "gitea-repositories-meta")
	assert.NoError(t, com.CopyDir(metaPath, setting.RepoRootPath))
}

type testCond struct {
	query interface{}
	args  []interface{}
}

// Cond create a condition with arguments for a test
func Cond(query interface{}, args ...interface{}) interface{} {
	return &testCond{query: query, args: args}
}

func whereConditions(sess *xorm.Session, conditions []interface{}) {
	for _, condition := range conditions {
		switch cond := condition.(type) {
		case *testCond:
			sess.Where(cond.query, cond.args...)
		default:
			sess.Where(cond)
		}
	}
}

func loadBeanIfExists(bean interface{}, conditions ...interface{}) (bool, error) {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	return sess.Get(bean)
}

// BeanExists for testing, check if a bean exists
func BeanExists(t testing.TB, bean interface{}, conditions ...interface{}) bool {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	return exists
}

// AssertExistsAndLoadBean assert that a bean exists and load it from the test
// database
func AssertExistsAndLoadBean(t testing.TB, bean interface{}, conditions ...interface{}) interface{} {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.True(t, exists,
		"Expected to find %+v (of type %T, with conditions %+v), but did not",
		bean, bean, conditions)
	return bean
}

// GetCount get the count of a bean
func GetCount(t testing.TB, bean interface{}, conditions ...interface{}) int {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	count, err := sess.Count(bean)
	assert.NoError(t, err)
	return int(count)
}

// AssertNotExistsBean assert that a bean does not exist in the test database
func AssertNotExistsBean(t testing.TB, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.False(t, exists)
}

// AssertExistsIf asserts that a bean exists or does not exist, depending on
// what is expected.
func AssertExistsIf(t *testing.T, expected bool, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.Equal(t, expected, exists)
}

// AssertSuccessfulInsert assert that beans is successfully inserted
func AssertSuccessfulInsert(t testing.TB, beans ...interface{}) {
	_, err := x.Insert(beans...)
	assert.NoError(t, err)
}

// AssertCount assert the count of a bean
func AssertCount(t testing.TB, bean interface{}, expected interface{}) {
	assert.EqualValues(t, expected, GetCount(t, bean))
}

// AssertInt64InRange assert value is in range [low, high]
func AssertInt64InRange(t testing.TB, low, high, value int64) {
	assert.True(t, value >= low && value <= high,
		"Expected value in range [%d, %d], found %d", low, high, value)
}
<commit_msg>Fix integer constant overflows in tests (#4616)<commit_after>// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package models

import (
	"fmt"
	"io/ioutil"
	"math"
	"net/url"
	"os"
	"path/filepath"
	"testing"
	"time"

	"code.gitea.io/gitea/modules/setting"

	"github.com/Unknwon/com"
	"github.com/go-xorm/core"
	"github.com/go-xorm/xorm"
	"github.com/stretchr/testify/assert"
	"gopkg.in/testfixtures.v2"
)

// NonexistentID an ID that will never exist
const NonexistentID = int64(math.MaxInt64)

// giteaRoot a path to the gitea root
var giteaRoot string

func fatalTestError(fmtStr string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, fmtStr, args...)
	os.Exit(1)
}

// MainTest a reusable TestMain(..) function for unit tests that need to use a
// test database. Creates the test database, and sets necessary settings.
func MainTest(m *testing.M, pathToGiteaRoot string) {
	var err error
	giteaRoot = pathToGiteaRoot
	fixturesDir := filepath.Join(pathToGiteaRoot, "models", "fixtures")
	if err = createTestEngine(fixturesDir); err != nil {
		fatalTestError("Error creating test engine: %v\n", err)
	}

	setting.AppURL = "https://try.gitea.io/"
	setting.RunUser = "runuser"
	setting.SSH.Port = 3000
	setting.SSH.Domain = "try.gitea.io"
	setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos")
	if err != nil {
		fatalTestError("TempDir: %v\n", err)
	}
	setting.AppDataPath, err = ioutil.TempDir(os.TempDir(), "appdata")
	if err != nil {
		fatalTestError("TempDir: %v\n", err)
	}
	setting.AppWorkPath = pathToGiteaRoot
	setting.StaticRootPath = pathToGiteaRoot
	setting.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/")
	if err != nil {
		fatalTestError("url.Parse: %v\n", err)
	}

	exitStatus := m.Run()
	if err = removeAllWithRetry(setting.RepoRootPath); err != nil {
		fatalTestError("os.RemoveAll: %v\n", err)
	}
	if err = removeAllWithRetry(setting.AppDataPath); err != nil {
		fatalTestError("os.RemoveAll: %v\n", err)
	}
	os.Exit(exitStatus)
}

func createTestEngine(fixturesDir string) error {
	var err error
	x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
	if err != nil {
		return err
	}
	x.SetMapper(core.GonicMapper{})
	if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
		return err
	}
	switch os.Getenv("GITEA_UNIT_TESTS_VERBOSE") {
	case "true", "1":
		x.ShowSQL(true)
	}

	return InitFixtures(&testfixtures.SQLite{}, fixturesDir)
}

func removeAllWithRetry(dir string) error {
	var err error
	for i := 0; i < 20; i++ {
		err = os.RemoveAll(dir)
		if err == nil {
			break
		}
		time.Sleep(100 * time.Millisecond)
	}
	return err
}

// PrepareTestDatabase load test fixtures into test database
func PrepareTestDatabase() error {
	return LoadFixtures()
}

// PrepareTestEnv prepares the environment for unit tests. Can only be called
// by tests that use the above MainTest(..) function.
func PrepareTestEnv(t testing.TB) {
	assert.NoError(t, PrepareTestDatabase())
	assert.NoError(t, removeAllWithRetry(setting.RepoRootPath))
	metaPath := filepath.Join(giteaRoot, "integrations", "gitea-repositories-meta")
	assert.NoError(t, com.CopyDir(metaPath, setting.RepoRootPath))
}

type testCond struct {
	query interface{}
	args  []interface{}
}

// Cond create a condition with arguments for a test
func Cond(query interface{}, args ...interface{}) interface{} {
	return &testCond{query: query, args: args}
}

func whereConditions(sess *xorm.Session, conditions []interface{}) {
	for _, condition := range conditions {
		switch cond := condition.(type) {
		case *testCond:
			sess.Where(cond.query, cond.args...)
		default:
			sess.Where(cond)
		}
	}
}

func loadBeanIfExists(bean interface{}, conditions ...interface{}) (bool, error) {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	return sess.Get(bean)
}

// BeanExists for testing, check if a bean exists
func BeanExists(t testing.TB, bean interface{}, conditions ...interface{}) bool {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	return exists
}

// AssertExistsAndLoadBean assert that a bean exists and load it from the test
// database
func AssertExistsAndLoadBean(t testing.TB, bean interface{}, conditions ...interface{}) interface{} {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.True(t, exists,
		"Expected to find %+v (of type %T, with conditions %+v), but did not",
		bean, bean, conditions)
	return bean
}

// GetCount get the count of a bean
func GetCount(t testing.TB, bean interface{}, conditions ...interface{}) int {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	count, err := sess.Count(bean)
	assert.NoError(t, err)
	return int(count)
}

// AssertNotExistsBean assert that a bean does not exist in the test database
func AssertNotExistsBean(t testing.TB, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.False(t, exists)
}

// AssertExistsIf asserts that a bean exists or does not exist, depending on
// what is expected.
func AssertExistsIf(t *testing.T, expected bool, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.Equal(t, expected, exists)
}

// AssertSuccessfulInsert assert that beans is successfully inserted
func AssertSuccessfulInsert(t testing.TB, beans ...interface{}) {
	_, err := x.Insert(beans...)
	assert.NoError(t, err)
}

// AssertCount assert the count of a bean
func AssertCount(t testing.TB, bean interface{}, expected interface{}) {
	assert.EqualValues(t, expected, GetCount(t, bean))
}

// AssertInt64InRange assert value is in range [low, high]
func AssertInt64InRange(t testing.TB, low, high, value int64) {
	assert.True(t, value >= low && value <= high,
		"Expected value in range [%d, %d], found %d", low, high, value)
}
<|endoftext|>


<commit_before>package tree

import "github.com/catorpilor/leetcode/utils"

func buildTree(inorder, postorder []int) *utils.TreeNode {
	return nil
}
<commit_msg>solve 106 using dfs<commit_after>package tree

import (
	"github.com/catorpilor/leetcode/utils"
)

func buildTree(inorder, postorder []int) *utils.TreeNode {
	return useDFS(inorder, postorder, 0, len(inorder)-1, 0, len(postorder)-1)
}

// useDFS time complexity O(N), space complexity O(1) ?
func useDFS(inorder, postorder []int, li, ri, lp, rp int) *utils.TreeNode {
	if li > ri || lp > rp {
		return nil
	}

	root := &utils.TreeNode{Val: postorder[rp]}
	pos := li
	for pos <= ri {
		if inorder[pos] == root.Val {
			break
		}
		pos++
	}
	leftNodes := pos - li
	// fmt.Printf("li:%d, ri:%d, lp:%d, rp:%d, pos:%d, lefeNode:%d\n", li, ri, lp, rp, pos, leftNodes)
	root.Left = useDFS(inorder, postorder, li, pos-1, lp, lp+leftNodes-1)
	root.Right = useDFS(inorder, postorder, pos+1, ri, lp+leftNodes, rp-1)
	return root
}
<|endoftext|>


<commit_before>// This is the boot2docker management utilty.
package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
)

const Version = "v0.7.0-dev" // during development we keep the -dev suffix

// B2D reprents boot2docker config.
var B2D struct {
	VBM        string // VirtualBox management utility
	SSH        string // SSH client executable
	VM         string // virtual machine name
	Dir        string // boot2docker directory
	ISO        string // boot2docker ISO image path
	Disk       string // VM disk image path
	DiskSize   int    // VM disk image size (MB)
	Memory     int    // VM memory size (MB)
	SSHPort    int    // host SSH port (forward to port 22 in VM)
	DockerPort int    // host Docker port (forward to port 4243 in VM)
}

var usageShort = fmt.Sprintf(`Usage: %s {help|init|start|up|ssh|save|pause|stop|poweroff|reset|restart|status|info|delete|download} [<vm>]
`, os.Args[0])

var usageLong = fmt.Sprintf(`Usage: %s <command> [<vm>]

boot2docker management utility.

Commands:

    init            Create a new boot2docker VM.
    up|start|boot   Start the VM from any state.
    ssh             Login to VM.
    save|suspend    Suspend the VM (saving running state to disk).
    down|stop|halt  Gracefully shutdown the VM.
    restart         Gracefully reboot the VM.
    poweroff        Forcefully shutdown the VM (might cause disk corruption).
    reset           Forcefully reboot the VM (might cause disk corruption).
    delete          Delete the boot2docker VM and its disk image.
    download        Download the boot2docker ISO image.
    info            Display the detailed information of the VM
    status          Display the current state of the VM.

`, os.Args[0])

func getCfgDir(name string) (string, error) {
	if b2dDir := os.Getenv("BOOT2DOCKER_CFG_DIR"); b2dDir != "" {
		return b2dDir, nil
	}

	// Unix
	if home := os.Getenv("HOME"); home != "" {
		return filepath.Join(home, name), nil
	}

	// Windows
	for _, env := range []string{
		"APPDATA",
		"LOCALAPPDATA",
		"USERPROFILE", // let's try USERPROFILE only as a very last resort
	} {
		if val := os.Getenv(env); val != "" {
			return filepath.Join(val, "boot2docker"), nil
		}
	}
	// ok, we've tried everything reasonable - now let's go for CWD
	cwd, err := os.Getwd()
	if err != nil {
		return "", err
	}
	return filepath.Join(cwd, name), nil
}

// Read configuration.
func config() (err error) {

	if B2D.Dir, err = getCfgDir(".boot2docker"); err != nil {
		return fmt.Errorf("failed to get current directory: %s", err)
	}
	cfgi, err := getConfigfile()

	B2D.VBM = cfgi.Get("", "VBM", "VBoxManage")
	B2D.SSH = cfgi.Get("", "BOOT2DOCKER_SSH", "ssh")
	B2D.VM = cfgi.Get("", "VM_NAME", "boot2docker-vm")

	B2D.ISO = cfgi.Get("", "BOOT2DOCKER_ISO", filepath.Join(B2D.Dir, "boot2docker.iso"))
	B2D.Disk = cfgi.Get("", "VM_DISK", filepath.Join(B2D.Dir, "boot2docker.vmdk"))

	if B2D.DiskSize, err = strconv.Atoi(cfgi.Get("", "VM_DISK_SIZE", "20000")); err != nil {
		return fmt.Errorf("invalid VM_DISK_SIZE: %s", err)
	}
	if B2D.DiskSize <= 0 {
		return fmt.Errorf("VM_DISK_SIZE way too small")
	}
	if B2D.Memory, err = strconv.Atoi(cfgi.Get("", "VM_MEM", "1024")); err != nil {
		return fmt.Errorf("invalid VM_MEM: %s", err)
	}
	if B2D.Memory <= 0 {
		return fmt.Errorf("VM_MEM way too small")
	}
	if B2D.SSHPort, err = strconv.Atoi(cfgi.Get("", "SSH_HOST_PORT", "2022")); err != nil {
		return fmt.Errorf("invalid SSH_HOST_PORT: %s", err)
	}
	if B2D.SSHPort <= 0 {
		return fmt.Errorf("invalid SSH_HOST_PORT: must be in the range of 1--65535; got %d", B2D.SSHPort)
	}
	if B2D.DockerPort, err = strconv.Atoi(cfgi.Get("", "DOCKER_PORT", "4243")); err != nil {
		return fmt.Errorf("invalid DOCKER_PORT: %s", err)
	}
	if B2D.DockerPort <= 0 {
		return fmt.Errorf("invalid DOCKER_PORT: must be in the range of 1--65535; got %d", B2D.DockerPort)
	}

	// TODO maybe allow flags to override ENV vars?
	flag.Parse()
	if vm := flag.Arg(1); vm != "" {
		B2D.VM = vm
	}
	return
}

func run() int {
	if err := config(); err != nil {
		logf("%s", err)
		return 1
	}

	if _, err := exec.LookPath(B2D.VBM); err != nil {
		logf("failed to locate VirtualBox management utility %q", B2D.VBM)
		return 2
	}

	switch cmd := flag.Arg(0); cmd {
	case "download":
		return cmdDownload()
	case "init":
		return cmdInit()
	case "start", "up", "boot", "resume":
		return cmdStart()
	case "ssh":
		return cmdSSH()
	case "save", "suspend":
		return cmdSave()
	case "pause":
		return cmdPause()
	case "halt", "down", "stop":
		return cmdStop()
	case "poweroff":
		return cmdPoweroff()
	case "restart":
		return cmdRestart()
	case "reset":
		return cmdReset()
	case "info":
		return cmdInfo()
	case "status":
		return cmdStatus()
	case "version":
		fmt.Println(Version)
		return 0
	case "help":
		logf(usageLong)
		return 0
	case "delete":
		return cmdDelete()
	case "":
		logf(usageShort)
		return 0
	default:
		logf("Unknown command '%s'", cmd)
		logf(usageShort)
		return 1
	}
}

func main() {
	os.Exit(run())
}
<commit_msg>Declare version vars to be injected during build<commit_after>// This is the boot2docker management utilty.
package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
)

// The following will be injected during the build process.
var (
	Version string
	GitSHA  string
)

// B2D reprents boot2docker config.
var B2D struct {
	VBM        string // VirtualBox management utility
	SSH        string // SSH client executable
	VM         string // virtual machine name
	Dir        string // boot2docker directory
	ISO        string // boot2docker ISO image path
	Disk       string // VM disk image path
	DiskSize   int    // VM disk image size (MB)
	Memory     int    // VM memory size (MB)
	SSHPort    int    // host SSH port (forward to port 22 in VM)
	DockerPort int    // host Docker port (forward to port 4243 in VM)
}

var usageShort = fmt.Sprintf(`Usage: %s {help|init|start|up|ssh|save|pause|stop|poweroff|reset|restart|status|info|delete|download} [<vm>]
`, os.Args[0])

var usageLong = fmt.Sprintf(`Usage: %s <command> [<vm>]

boot2docker management utility.

Commands:

    init            Create a new boot2docker VM.
    up|start|boot   Start the VM from any state.
    ssh             Login to VM.
    save|suspend    Suspend the VM (saving running state to disk).
    down|stop|halt  Gracefully shutdown the VM.
    restart         Gracefully reboot the VM.
    poweroff        Forcefully shutdown the VM (might cause disk corruption).
    reset           Forcefully reboot the VM (might cause disk corruption).
    delete          Delete the boot2docker VM and its disk image.
    download        Download the boot2docker ISO image.
    info            Display the detailed information of the VM
    status          Display the current state of the VM.

`, os.Args[0])

func getCfgDir(name string) (string, error) {
	if b2dDir := os.Getenv("BOOT2DOCKER_CFG_DIR"); b2dDir != "" {
		return b2dDir, nil
	}

	// Unix
	if home := os.Getenv("HOME"); home != "" {
		return filepath.Join(home, name), nil
	}

	// Windows
	for _, env := range []string{
		"APPDATA",
		"LOCALAPPDATA",
		"USERPROFILE", // let's try USERPROFILE only as a very last resort
	} {
		if val := os.Getenv(env); val != "" {
			return filepath.Join(val, "boot2docker"), nil
		}
	}
	// ok, we've tried everything reasonable - now let's go for CWD
	cwd, err := os.Getwd()
	if err != nil {
		return "", err
	}
	return filepath.Join(cwd, name), nil
}

// Read configuration.
func config() (err error) {

	if B2D.Dir, err = getCfgDir(".boot2docker"); err != nil {
		return fmt.Errorf("failed to get current directory: %s", err)
	}
	cfgi, err := getConfigfile()

	B2D.VBM = cfgi.Get("", "VBM", "VBoxManage")
	B2D.SSH = cfgi.Get("", "BOOT2DOCKER_SSH", "ssh")
	B2D.VM = cfgi.Get("", "VM_NAME", "boot2docker-vm")

	B2D.ISO = cfgi.Get("", "BOOT2DOCKER_ISO", filepath.Join(B2D.Dir, "boot2docker.iso"))
	B2D.Disk = cfgi.Get("", "VM_DISK", filepath.Join(B2D.Dir, "boot2docker.vmdk"))

	if B2D.DiskSize, err = strconv.Atoi(cfgi.Get("", "VM_DISK_SIZE", "20000")); err != nil {
		return fmt.Errorf("invalid VM_DISK_SIZE: %s", err)
	}
	if B2D.DiskSize <= 0 {
		return fmt.Errorf("VM_DISK_SIZE way too small")
	}
	if B2D.Memory, err = strconv.Atoi(cfgi.Get("", "VM_MEM", "1024")); err != nil {
		return fmt.Errorf("invalid VM_MEM: %s", err)
	}
	if B2D.Memory <= 0 {
		return fmt.Errorf("VM_MEM way too small")
	}
	if B2D.SSHPort, err = strconv.Atoi(cfgi.Get("", "SSH_HOST_PORT", "2022")); err != nil {
		return fmt.Errorf("invalid SSH_HOST_PORT: %s", err)
	}
	if B2D.SSHPort <= 0 {
		return fmt.Errorf("invalid SSH_HOST_PORT: must be in the range of 1--65535; got %d", B2D.SSHPort)
	}
	if B2D.DockerPort, err = strconv.Atoi(cfgi.Get("", "DOCKER_PORT", "4243")); err != nil {
		return fmt.Errorf("invalid DOCKER_PORT: %s", err)
	}
	if B2D.DockerPort <= 0 {
		return fmt.Errorf("invalid DOCKER_PORT: must be in the range of 1--65535; got %d", B2D.DockerPort)
	}

	// TODO maybe allow flags to override ENV vars?
	flag.Parse()
	if vm := flag.Arg(1); vm != "" {
		B2D.VM = vm
	}
	return
}

func run() int {
	if err := config(); err != nil {
		logf("%s", err)
		return 1
	}

	if _, err := exec.LookPath(B2D.VBM); err != nil {
		logf("failed to locate VirtualBox management utility %q", B2D.VBM)
		return 2
	}

	switch cmd := flag.Arg(0); cmd {
	case "download":
		return cmdDownload()
	case "init":
		return cmdInit()
	case "start", "up", "boot", "resume":
		return cmdStart()
	case "ssh":
		return cmdSSH()
	case "save", "suspend":
		return cmdSave()
	case "pause":
		return cmdPause()
	case "halt", "down", "stop":
		return cmdStop()
	case "poweroff":
		return cmdPoweroff()
	case "restart":
		return cmdRestart()
	case "reset":
		return cmdReset()
	case "info":
		return cmdInfo()
	case "status":
		return cmdStatus()
	case "version":
		fmt.Println(Version)
		return 0
	case "help":
		logf(usageLong)
		return 0
	case "delete":
		return cmdDelete()
	case "":
		logf(usageShort)
		return 0
	default:
		logf("Unknown command '%s'", cmd)
		logf(usageShort)
		return 1
	}
}

func main() {
	os.Exit(run())
}
<|endoftext|>


<commit_before>package resource

import (
	"encoding/json"
	"io"
	"net/http"
	"regexp"
	"sort"
	"strings"

	"github.com/qor/qor"
)

func convertMapToMetaValues(values map[string]interface{}, metaors []Metaor) (*MetaValues, error) {
	metaValues := &MetaValues{}
	metaorMap := make(map[string]Metaor)
	for _, metaor := range metaors {
		metaorMap[metaor.GetName()] = metaor
	}

	for key, value := range values {
		var metaValue *MetaValue
		metaor := metaorMap[key]
		var childMeta []Metaor
		if metaor != nil {
			childMeta = metaor.GetMetas()
		}

		switch result := value.(type) {
		case map[string]interface{}:
			if children, err := convertMapToMetaValues(result, childMeta); err == nil {
				metaValue = &MetaValue{Name: key, Meta: metaor, MetaValues: children}
			}
		case []interface{}:
			for idx, r := range result {
				if mr, ok := r.(map[string]interface{}); ok {
					if children, err := convertMapToMetaValues(mr, childMeta); err == nil {
						metaValue := &MetaValue{Name: key, Meta: metaor, MetaValues: children, Index: idx}
						metaValues.Values = append(metaValues.Values, metaValue)
					}
				} else {
					metaValue := &MetaValue{Name: key, Value: result, Meta: metaor}
					metaValues.Values = append(metaValues.Values, metaValue)
					break
				}
			}
		default:
			metaValue = &MetaValue{Name: key, Value: value, Meta: metaor}
		}

		if metaValue != nil {
			metaValues.Values = append(metaValues.Values, metaValue)
		}
	}
	return metaValues, nil
}

// ConvertJSONToMetaValues convert json to meta values
func ConvertJSONToMetaValues(reader io.Reader, metaors []Metaor) (*MetaValues, error) {
	var (
		err     error
		values  = map[string]interface{}{}
		decoder = json.NewDecoder(reader)
	)

	if err = decoder.Decode(&values); err == nil {
		return convertMapToMetaValues(values, metaors)
	}
	return nil, err
}

var (
	isCurrentLevel = regexp.MustCompile("^[^.]+$")
	isNextLevel    = regexp.MustCompile(`^(([^.\[\]]+)(\[\d+\])?)(?:(\.[^.]+)+)$`)
)

// ConvertFormToMetaValues convert form to meta values
func ConvertFormToMetaValues(request *http.Request, metaors []Metaor, prefix string) (*MetaValues, error) {
	metaValues := &MetaValues{}
	metaorsMap := map[string]Metaor{}
	convertedNextLevel := map[string]bool{}
	nestedStructIndex := map[string]int{}
	for _, metaor := range metaors {
		metaorsMap[metaor.GetName()] = metaor
	}

	newMetaValue := func(key string, value interface{}) {
		if strings.HasPrefix(key, prefix) {
			var metaValue *MetaValue
			key = strings.TrimPrefix(key, prefix)

			if matches := isCurrentLevel.FindStringSubmatch(key); len(matches) > 0 {
				name := matches[0]
				metaValue = &MetaValue{Name: name, Value: value, Meta: metaorsMap[name]}
			} else if matches := isNextLevel.FindStringSubmatch(key); len(matches) > 0 {
				name := matches[1]
				if _, ok := convertedNextLevel[name]; !ok {
					var metaors []Metaor
					convertedNextLevel[name] = true
					metaor := metaorsMap[matches[2]]
					if metaor != nil {
						metaors = metaor.GetMetas()
					}

					if children, err := ConvertFormToMetaValues(request, metaors, prefix+name+"."); err == nil {
						nestedName := prefix + matches[2]
						if _, ok := nestedStructIndex[nestedName]; ok {
							nestedStructIndex[nestedName]++
						} else {
							nestedStructIndex[nestedName] = 0
						}
						metaValue = &MetaValue{Name: matches[2], Meta: metaor, MetaValues: children, Index: nestedStructIndex[nestedName]}
					}
				}
			}

			if metaValue != nil {
				metaValues.Values = append(metaValues.Values, metaValue)
			}
		}
	}

	var sortedFormKeys []string
	for key := range request.Form {
		sortedFormKeys = append(sortedFormKeys, key)
	}
	sort.Strings(sortedFormKeys)

	for _, key := range sortedFormKeys {
		newMetaValue(key, request.Form[key])
	}

	if request.MultipartForm != nil {
		sortedFormKeys = []string{}
		for key := range request.MultipartForm.File {
			sortedFormKeys = append(sortedFormKeys, key)
		}
		sort.Strings(sortedFormKeys)

		for _, key := range sortedFormKeys {
			newMetaValue(key, request.MultipartForm.File[key])
		}
	}
	return metaValues, nil
}

// Decode decode context to result according to resource definition
func Decode(context *qor.Context, result interface{}, res Resourcer) error {
	var errors qor.Errors
	var err error
	var metaValues *MetaValues
	metaors := res.GetMetas([]string{})

	if strings.Contains(context.Request.Header.Get("Content-Type"), "json") {
		metaValues, err = ConvertJSONToMetaValues(context.Request.Body, metaors)
		context.Request.Body.Close()
	} else {
		metaValues, err = ConvertFormToMetaValues(context.Request, metaors, "QorResource.")
	}

	errors.AddError(err)
	errors.AddError(DecodeToResource(res, result, metaValues, context).Start())
	return errors
}
<commit_msg>Fix sort form keys<commit_after>package resource

import (
	"encoding/json"
	"io"
	"net/http"
	"regexp"
	"sort"
	"strings"

	"github.com/qor/qor"
)

func convertMapToMetaValues(values map[string]interface{}, metaors []Metaor) (*MetaValues, error) {
	metaValues := &MetaValues{}
	metaorMap := make(map[string]Metaor)
	for _, metaor := range metaors {
		metaorMap[metaor.GetName()] = metaor
	}

	for key, value := range values {
		var metaValue *MetaValue
		metaor := metaorMap[key]
		var childMeta []Metaor
		if metaor != nil {
			childMeta = metaor.GetMetas()
		}

		switch result := value.(type) {
		case map[string]interface{}:
			if children, err := convertMapToMetaValues(result, childMeta); err == nil {
				metaValue = &MetaValue{Name: key, Meta: metaor, MetaValues: children}
			}
		case []interface{}:
			for idx, r := range result {
				if mr, ok := r.(map[string]interface{}); ok {
					if children, err := convertMapToMetaValues(mr, childMeta); err == nil {
						metaValue := &MetaValue{Name: key, Meta: metaor, MetaValues: children, Index: idx}
						metaValues.Values = append(metaValues.Values, metaValue)
					}
				} else {
					metaValue := &MetaValue{Name: key, Value: result, Meta: metaor}
					metaValues.Values = append(metaValues.Values, metaValue)
					break
				}
			}
		default:
			metaValue = &MetaValue{Name: key, Value: value, Meta: metaor}
		}

		if metaValue != nil {
			metaValues.Values = append(metaValues.Values, metaValue)
		}
	}
	return metaValues, nil
}

// ConvertJSONToMetaValues convert json to meta values
func ConvertJSONToMetaValues(reader io.Reader, metaors []Metaor) (*MetaValues, error) {
	var (
		err     error
		values  = map[string]interface{}{}
		decoder = json.NewDecoder(reader)
	)

	if err = decoder.Decode(&values); err == nil {
		return convertMapToMetaValues(values, metaors)
	}
	return nil, err
}

var (
	isCurrentLevel = regexp.MustCompile("^[^.]+$")
	isNextLevel    = regexp.MustCompile(`^(([^.\[\]]+)(\[\d+\])?)(?:(\.[^.]+)+)$`)
)

// ConvertFormToMetaValues convert form to meta values
func ConvertFormToMetaValues(request *http.Request, metaors []Metaor, prefix string) (*MetaValues, error) {
	metaValues := &MetaValues{}
	metaorsMap := map[string]Metaor{}
	convertedNextLevel := map[string]bool{}
	nestedStructIndex := map[string]int{}
	for _, metaor := range metaors {
		metaorsMap[metaor.GetName()] = metaor
	}

	newMetaValue := func(key string, value interface{}) {
		if strings.HasPrefix(key, prefix) {
			var metaValue *MetaValue
			key = strings.TrimPrefix(key, prefix)

			if matches := isCurrentLevel.FindStringSubmatch(key); len(matches) > 0 {
				name := matches[0]
				metaValue = &MetaValue{Name: name, Value: value, Meta: metaorsMap[name]}
			} else if matches := isNextLevel.FindStringSubmatch(key); len(matches) > 0 {
				name := matches[1]
				if _, ok := convertedNextLevel[name]; !ok {
					var metaors []Metaor
					convertedNextLevel[name] = true
					metaor := metaorsMap[matches[2]]
					if metaor != nil {
						metaors = metaor.GetMetas()
					}

					if children, err := ConvertFormToMetaValues(request, metaors, prefix+name+"."); err == nil {
						nestedName := prefix + matches[2]
						if _, ok := nestedStructIndex[nestedName]; ok {
							nestedStructIndex[nestedName]++
						} else {
							nestedStructIndex[nestedName] = 0
						}
						metaValue = &MetaValue{Name: matches[2], Meta: metaor, MetaValues: children, Index: nestedStructIndex[nestedName]}
					}
				}
			}

			if metaValue != nil {
				metaValues.Values = append(metaValues.Values, metaValue)
			}
		}
	}

	var sortedFormKeys []string
	for key := range request.Form {
		sortedFormKeys = append(sortedFormKeys, key)
	}

	replaceIdxRegexp := regexp.MustCompile(`\[\d+\]`)
	orderFunc := func(i, j int) bool { // true for first
		str1 := replaceIdxRegexp.ReplaceAllString(sortedFormKeys[i], "[:number:]")
		str2 := replaceIdxRegexp.ReplaceAllString(sortedFormKeys[j], "[:number:]")

		if str1 == str2 {
			matched1 := replaceIdxRegexp.FindStringSubmatch(sortedFormKeys[i])
			matched2 := replaceIdxRegexp.FindStringSubmatch(sortedFormKeys[j])
			if len(matched2) > len(matched1) {
				return false
			}

			for x := 0; x < len(matched1); x++ {
				if matched1[x] != matched2[x] {
					if len(matched1[x]) != len(matched2[x]) {
						return len(matched1[x]) < len(matched2[x])
					}
					return strings.Compare(matched1[x], matched2[x]) < 0
				}
			}
		}

		return strings.Compare(str1, str2) < 0
	}
	sort.Slice(sortedFormKeys, orderFunc)

	for _, key := range sortedFormKeys {
		newMetaValue(key, request.Form[key])
	}

	if request.MultipartForm != nil {
		sortedFormKeys = []string{}
		for key := range request.MultipartForm.File {
			sortedFormKeys = append(sortedFormKeys, key)
		}
		sort.Slice(sortedFormKeys, orderFunc)

		for _, key := range sortedFormKeys {
			newMetaValue(key, request.MultipartForm.File[key])
		}
	}
	return metaValues, nil
}

// Decode decode context to result according to resource definition
func Decode(context *qor.Context, result interface{}, res Resourcer) error {
	var errors qor.Errors
	var err error
	var metaValues *MetaValues
	metaors := res.GetMetas([]string{})

	if strings.Contains(context.Request.Header.Get("Content-Type"), "json") {
		metaValues, err = ConvertJSONToMetaValues(context.Request.Body, metaors)
		context.Request.Body.Close()
	} else {
		metaValues, err = ConvertFormToMetaValues(context.Request, metaors, "QorResource.")
	}

	errors.AddError(err)
	errors.AddError(DecodeToResource(res, result, metaValues, context).Start())
	return errors
}
<|endoftext|>


<commit_before>package main

import "fmt"

func main() {

    for i := 0; i <= 10; i ++ {
        fmt.Println(i)
    }
}<commit_msg>run go-fmt<commit_after>package main

import "fmt"

func main() {

	for i := 0; i <= 10; i++ {
		fmt.Println(i)
	}
}
<|endoftext|>


<commit_before>// Package inference implements an in-memory store for inference
// RDFS Rules:
// 1. (x p y) -> (p rdf:type rdf:Property)
// 2. (p rdfs:domain c), (x p y) -> (x rdf:type c)
// 3. (p rdfs:range c), (x p y) -> (y rdf:type c)
// 4a. (x p y) -> (x rdf:type rdfs:Resource)
// 4b. (x p y) -> (y rdf:type rdfs:Resource)
// 5. (p rdfs:subPropertyOf q), (q rdfs:subPropertyOf r) -> (p rdfs:subPropertyOf r)
// 6. (p rdf:type Property) -> (p rdfs:subPropertyOf p)
// 7. (p rdf:subPropertyOf q), (x p y) -> (x q y)
// 8. (c rdf:type rdfs:Class) -> (c rdfs:subClassOf rdfs:Resource)
// 9. (c rdfs:subClassOf d), (x rdf:type c) -> (x rdf:type d)
// 10. (c rdf:type rdfs:Class) -> (c rdfs:subClassOf c)
// 11. (c rdfs:subClassOf d), (d rdfs:subClassOf e) -> (c rdfs:subClassOf e)
// 12. (p rdf:type rdfs:ContainerMembershipProperty) -> (p rdfs:subPropertyOf rdfs:member)
// 13. (x rdf:type rdfs:Datatype) -> (x rdfs:subClassOf rdfs:Literal)
// Exported from: https://www.researchgate.net/figure/RDF-RDFS-entailment-rules_tbl1_268419911
package inference

import (
	"github.com/cayleygraph/quad"
	"github.com/cayleygraph/quad/voc/rdf"
	"github.com/cayleygraph/quad/voc/rdfs"
)

// Class represents a RDF Class with the links to classes and other properties
type Class struct {
	name          quad.Value
	references    int
	super         map[*Class]struct{}
	sub           map[*Class]struct{}
	ownProperties map[*Property]struct{}
	inProperties  map[*Property]struct{}
	store         *Store
}

func newClass(name quad.Value, store *Store) *Class {
	return &Class{
		name:          name,
		references:    1,
		super:         map[*Class]struct{}{},
		sub:           map[*Class]struct{}{},
		ownProperties: map[*Property]struct{}{},
		inProperties:  map[*Property]struct{}{},
		store:         store,
	}
}

// Name returns the class's name
func (class *Class) Name() quad.Value {
	return class.name
}

// IsSubClassOf recursively checks whether class is a superClass
func (class *Class) IsSubClassOf(superClass *Class) bool {
	if class == superClass {
		return true
	}
	if superClass.name == quad.IRI(rdfs.Resource) {
		return true
	}
	if _, ok := class.super[superClass]; ok {
		return true
	}
	for s := range class.super {
		if s.IsSubClassOf(superClass) {
			return true
		}
	}
	return false
}

func (class *Class) removeReference() {
	class.references--
	if class.references == 0 {
		delete(class.store.classes, class.name)
	}
}

// Property represents a RDF Property with the links to classes and other properties
type Property struct {
	name       quad.Value
	references int
	domain     *Class
	_range     *Class
	super      map[*Property]struct{}
	sub        map[*Property]struct{}
	store      *Store
}

func newProperty(name quad.Value, store *Store) *Property {
	return &Property{
		name:       name,
		references: 1,
		super:      map[*Property]struct{}{},
		sub:        map[*Property]struct{}{},
		store:      store,
	}
}

// Name returns the property's name
func (property *Property) Name() quad.Value {
	return property.name
}

// Domain returns the domain of the property
func (property *Property) Domain() *Class {
	return property.domain
}

// Range returns the range of the property
func (property *Property) Range() *Class {
	return property._range
}

// IsSubPropertyOf recursively checks whether property is a superProperty
func (property *Property) IsSubPropertyOf(superProperty *Property) bool {
	if property == superProperty {
		return true
	}
	if _, ok := property.super[superProperty]; ok {
		return true
	}
	for s := range property.super {
		if s.IsSubPropertyOf(superProperty) {
			return true
		}
	}
	return false
}

func (property *Property) removeReference() {
	property.references--
	if property.references == 0 {
		delete(property.store.properties, property.name)
	}
}

// Store is a struct holding the inference data
type Store struct {
	classes    map[quad.Value]*Class
	properties map[quad.Value]*Property
}

// NewStore creates a new Store
func NewStore() Store {
	store := Store{
		classes:    map[quad.Value]*Class{},
		properties: map[quad.Value]*Property{},
	}
	rdfsResource := newClass(quad.IRI(rdfs.Resource), &store)
	store.classes[rdfsResource.name] = rdfsResource
	return store
}

// GetClass returns a class struct for class name, if it doesn't exist in the store then it returns nil
func (store *Store) GetClass(name quad.Value) *Class {
	return store.classes[name]
}

// GetProperty returns a class struct for property name, if it doesn't exist in the store then it returns nil
func (store *Store) GetProperty(name quad.Value) *Property {
	return store.properties[name]
}

func (store *Store) addClass(class quad.Value) *Class {
	if c, ok := store.classes[class]; ok {
		c.references++
		return c
	}
	c := newClass(class, store)
	store.classes[class] = c
	return c
}

func (store *Store) addProperty(property quad.Value) *Property {
	if p, ok := store.properties[property]; ok {
		p.references++
		return p
	}
	p := newProperty(property, store)
	store.properties[property] = p
	return p
}

func (store *Store) addClassRelationship(child quad.Value, parent quad.Value) {
	parentClass := store.addClass(parent)
	childClass := store.addClass(child)
	if _, ok := parentClass.sub[childClass]; !ok {
		parentClass.sub[childClass] = struct{}{}
		childClass.super[parentClass] = struct{}{}
	}
}

func (store *Store) addPropertyRelationship(child quad.Value, parent quad.Value) {
	parentProperty := store.addProperty(parent)
	childProperty := store.addProperty(child)
	if _, ok := parentProperty.sub[childProperty]; !ok {
		parentProperty.sub[childProperty] = struct{}{}
		childProperty.super[parentProperty] = struct{}{}
	}
}

func (store *Store) setPropertyDomain(property quad.Value, domain quad.Value) {
	p := store.addProperty(property)
	class := store.addClass(domain)
	// FIXME(iddan): Currently doesn't support multiple domains as they are very rare
	p.domain = class
	class.ownProperties[p] = struct{}{}
}

func (store *Store) setPropertyRange(property quad.Value, _range quad.Value) {
	p := store.addProperty(property)
	class := store.addClass(_range)
	p._range = class
	// FIXME(iddan): Currently doesn't support multiple ranges as they are very rare
	class.inProperties[p] = struct{}{}
}

// ProcessQuad is used to update the store with a new quad
func (store *Store) ProcessQuad(q quad.Quad) {
	subject, predicate, object := q.Subject, q.Predicate, q.Object
	predicateIRI, ok := predicate.(quad.IRI)
	if !ok {
		return
	}
	switch predicateIRI {
	case rdf.Type:
		if _, ok := object.(quad.BNode); ok {
			store.addClass(object)
		}
		objectIRI, ok := object.(quad.IRI)
		if !ok {
			return
		}
		switch objectIRI {
		case rdfs.Class:
			store.addClass(subject)
		case rdf.Property:
			store.addProperty(subject)
		default:
			store.addClass(object)
		}
	case rdfs.SubPropertyOf:
		store.addPropertyRelationship(subject, object)
	case rdfs.SubClassOf:
		store.addClassRelationship(subject, object)
	case rdfs.Domain:
		store.setPropertyDomain(subject, object)
	case rdfs.Range:
		store.setPropertyRange(subject, object)
	default:
		store.addProperty(predicate)
	}
}

// ProcessQuads is used to update the store with multiple quads
func (store *Store) ProcessQuads(quads []quad.Quad) {
	for _, q := range quads {
		store.ProcessQuad(q)
	}
}

func (store *Store) deleteClass(class quad.Value) {
	if c, ok := store.classes[class]; ok {
		for sub := range c.sub {
			c.removeReference()
			delete(sub.super, c)
		}
		for super := range c.super {
			c.removeReference()
			delete(super.sub, c)
		}
		delete(store.classes, class)
	}
}

func (store *Store) deleteProperty(property quad.Value) {
	if p, ok := store.properties[property]; ok {
		for super := range p.super {
			p.removeReference()
			delete(super.sub, p)
		}
		for sub := range p.sub {
			p.removeReference()
			delete(sub.super, p)
		}
		delete(store.properties, property)
	}
}

func (store *Store) deleteClassRelationship(child quad.Value, parent quad.Value) {
	parentClass := store.GetClass(parent)
	childClass := store.GetClass(child)
	if _, ok := parentClass.sub[childClass]; ok {
		parentClass.removeReference()
		delete(parentClass.sub, childClass)
		childClass.removeReference()
		delete(childClass.super, parentClass)
	}
}

func (store *Store) deletePropertyRelationship(child quad.Value, parent quad.Value) {
	parentProperty := store.GetProperty(parent)
	childProperty := store.GetProperty(child)
	if _, ok := parentProperty.sub[childProperty]; ok {
		parentProperty.removeReference()
		delete(parentProperty.sub, childProperty)
		childProperty.removeReference()
		delete(childProperty.super, parentProperty)
	}
}

func (store *Store) unsetPropertyDomain(property quad.Value, domain quad.Value) {
	p := store.GetProperty(property)
	class := store.GetClass(domain)
	// FIXME(iddan): Currently doesn't support multiple domains as they are very rare
	p.domain = nil
	delete(class.ownProperties, p)
	p.removeReference()
	class.removeReference()
}

func (store *Store) unsetPropertyRange(property quad.Value, _range quad.Value) {
	p := store.GetProperty(property)
	class := store.GetClass(_range)
	p._range = nil
	// FIXME(iddan): Currently doesn't support multiple ranges as they are very rare
	delete(class.inProperties, p)
	p.removeReference()
	class.removeReference()
}

// UnprocessQuad is used to delete a quad from the store
func (store *Store) UnprocessQuad(q quad.Quad) {
	subject, predicate, object := q.Subject, q.Predicate, q.Object
	predicateIRI, ok := predicate.(quad.IRI)
	if !ok {
		return
	}
	switch predicateIRI {
	case rdf.Type:
		objectIRI, ok := object.(quad.IRI)
		if !ok {
			return
		}
		switch objectIRI {
		case rdfs.Class:
			store.deleteClass(subject)
		case rdf.Property:
			store.deleteProperty(subject)
		default:
			store.deleteClass(object)
		}
	case rdfs.SubPropertyOf:
		store.deletePropertyRelationship(subject, object)
	case rdfs.SubClassOf:
		store.deleteClassRelationship(subject, object)
	case rdfs.Domain:
		store.unsetPropertyDomain(subject, object)
	case rdfs.Range:
		store.unsetPropertyRange(subject, object)
	default:
		store.deleteProperty(predicate)
	}
}

// UnprocessQuads is used to delete multiple quads from the store
func (store *Store) UnprocessQuads(quads []quad.Quad) {
	for _, q := range quads {
		store.UnprocessQuad(q)
	}
}
<commit_msg>Document which implemented<commit_after>// Package inference implements an in-memory store for inference
// RDFS Rules:
// 1. (x p y) -> (p rdf:type rdf:Property)
// 2. (p rdfs:domain c), (x p y) -> (x rdf:type c)
// 3. (p rdfs:range c), (x p y) -> (y rdf:type c)
// 4a. (x p y) -> (x rdf:type rdfs:Resource)
// 4b. (x p y) -> (y rdf:type rdfs:Resource)
// 5. (p rdfs:subPropertyOf q), (q rdfs:subPropertyOf r) -> (p rdfs:subPropertyOf r)
// 6. (p rdf:type Property) -> (p rdfs:subPropertyOf p)
// 7. (p rdf:subPropertyOf q), (x p y) -> (x q y)
// 8. (c rdf:type rdfs:Class) -> (c rdfs:subClassOf rdfs:Resource)
// 9. (c rdfs:subClassOf d), (x rdf:type c) -> (x rdf:type d)
// 10. (c rdf:type rdfs:Class) -> (c rdfs:subClassOf c)
// 11. (c rdfs:subClassOf d), (d rdfs:subClassOf e) -> (c rdfs:subClassOf e)
// 12. (p rdf:type rdfs:ContainerMembershipProperty) -> (p rdfs:subPropertyOf rdfs:member)
// 13. (x rdf:type rdfs:Datatype) -> (x rdfs:subClassOf rdfs:Literal)
// Exported from: https://www.researchgate.net/figure/RDF-RDFS-entailment-rules_tbl1_268419911
// Implemented here:
// 1 5 6 8 10 11
package inference

import (
	"github.com/cayleygraph/quad"
	"github.com/cayleygraph/quad/voc/rdf"
	"github.com/cayleygraph/quad/voc/rdfs"
)

// Class represents a RDF Class with the links to classes and other properties
type Class struct {
	name          quad.Value
	references    int
	super         map[*Class]struct{}
	sub           map[*Class]struct{}
	ownProperties map[*Property]struct{}
	inProperties  map[*Property]struct{}
	store         *Store
}

func newClass(name quad.Value, store *Store) *Class {
	return &Class{
		name:          name,
		references:    1,
		super:         map[*Class]struct{}{},
		sub:           map[*Class]struct{}{},
		ownProperties: map[*Property]struct{}{},
		inProperties:  map[*Property]struct{}{},
		store:         store,
	}
}

// Name returns the class's name
func (class *Class) Name() quad.Value {
	return class.name
}

// IsSubClassOf recursively checks whether class is a superClass
func (class *Class) IsSubClassOf(superClass *Class) bool {
	if class == superClass {
		return true
	}
	if superClass.name == quad.IRI(rdfs.Resource) {
		return true
	}
	if _, ok := class.super[superClass]; ok {
		return true
	}
	for s := range class.super {
		if s.IsSubClassOf(superClass) {
			return true
		}
	}
	return false
}

func (class *Class) removeReference() {
	class.references--
	if class.references == 0 {
		delete(class.store.classes, class.name)
	}
}

// Property represents a RDF Property with the links to classes and other properties
type Property struct {
	name       quad.Value
	references int
	domain     *Class
	_range     *Class
	super      map[*Property]struct{}
	sub        map[*Property]struct{}
	store      *Store
}

func newProperty(name quad.Value, store *Store) *Property {
	return &Property{
		name:       name,
		references: 1,
		super:      map[*Property]struct{}{},
		sub:        map[*Property]struct{}{},
		store:      store,
	}
}

// Name returns the property's name
func (property *Property) Name() quad.Value {
	return property.name
}

// Domain returns the domain of the property
func (property *Property) Domain() *Class {
	return property.domain
}

// Range returns the range of the property
func (property *Property) Range() *Class {
	return property._range
}

// IsSubPropertyOf recursively checks whether property is a superProperty
func (property *Property) IsSubPropertyOf(superProperty *Property) bool {
	if property == superProperty {
		return true
	}
	if _, ok := property.super[superProperty]; ok {
		return true
	}
	for s := range property.super {
		if s.IsSubPropertyOf(superProperty) {
			return true
		}
	}
	return false
}

func (property *Property) removeReference() {
	property.references--
	if property.references == 0 {
		delete(property.store.properties, property.name)
	}
}

// Store is a struct holding the inference data
type Store struct {
	classes    map[quad.Value]*Class
	properties map[quad.Value]*Property
}

// NewStore creates a new Store
func NewStore() Store {
	store := Store{
		classes:    map[quad.Value]*Class{},
		properties: map[quad.Value]*Property{},
	}
	rdfsResource := newClass(quad.IRI(rdfs.Resource), &store)
	store.classes[rdfsResource.name] = rdfsResource
	return store
}

// GetClass returns a class struct for class name, if it doesn't exist in the store then it returns nil
func (store *Store) GetClass(name quad.Value) *Class {
	return store.classes[name]
}

// GetProperty returns a class struct for property name, if it doesn't exist in the store then it returns nil
func (store *Store) GetProperty(name quad.Value) *Property {
	return store.properties[name]
}

func (store *Store) addClass(class quad.Value) *Class {
	if c, ok := store.classes[class]; ok {
		c.references++
		return c
	}
	c := newClass(class, store)
	store.classes[class] = c
	return c
}

func (store *Store) addProperty(property quad.Value) *Property {
	if p, ok := store.properties[property]; ok {
		p.references++
		return p
	}
	p := newProperty(property, store)
	store.properties[property] = p
	return p
}

func (store *Store) addClassRelationship(child quad.Value, parent quad.Value) {
	parentClass := store.addClass(parent)
	childClass := store.addClass(child)
	if _, ok := parentClass.sub[childClass]; !ok {
		parentClass.sub[childClass] = struct{}{}
		childClass.super[parentClass] = struct{}{}
	}
}

func (store *Store) addPropertyRelationship(child quad.Value, parent quad.Value) {
	parentProperty := store.addProperty(parent)
	childProperty := store.addProperty(child)
	if _, ok := parentProperty.sub[childProperty]; !ok {
		parentProperty.sub[childProperty] = struct{}{}
		childProperty.super[parentProperty] = struct{}{}
	}
}

func (store *Store) setPropertyDomain(property quad.Value, domain quad.Value) {
	p := store.addProperty(property)
	class := store.addClass(domain)
	// FIXME(iddan): Currently doesn't support multiple domains as they are very rare
	p.domain = class
	class.ownProperties[p] = struct{}{}
}

func (store *Store) setPropertyRange(property quad.Value, _range quad.Value) {
	p := store.addProperty(property)
	class := store.addClass(_range)
	p._range = class
	// FIXME(iddan): Currently doesn't support multiple ranges as they are very rare
	class.inProperties[p] = struct{}{}
}

// ProcessQuad is used to update the store with a new quad
func (store *Store) ProcessQuad(q quad.Quad) {
	subject, predicate, object := q.Subject, q.Predicate, q.Object
	predicateIRI, ok := predicate.(quad.IRI)
	if !ok {
		return
	}
	switch predicateIRI {
	case rdf.Type:
		if _, ok := object.(quad.BNode); ok {
			store.addClass(object)
		}
		objectIRI, ok := object.(quad.IRI)
		if !ok {
			return
		}
		switch objectIRI {
		case rdfs.Class:
			store.addClass(subject)
		case rdf.Property:
			store.addProperty(subject)
		default:
			store.addClass(object)
		}
	case rdfs.SubPropertyOf:
		store.addPropertyRelationship(subject, object)
	case rdfs.SubClassOf:
		store.addClassRelationship(subject, object)
	case rdfs.Domain:
		store.setPropertyDomain(subject, object)
	case rdfs.Range:
		store.setPropertyRange(subject, object)
	default:
		store.addProperty(predicate)
	}
}

// ProcessQuads is used to update the store with multiple quads
func (store *Store) ProcessQuads(quads []quad.Quad) {
	for _, q := range quads {
		store.ProcessQuad(q)
	}
}

func (store *Store) deleteClass(class quad.Value) {
	if c, ok := store.classes[class]; ok {
		for sub := range c.sub {
			c.removeReference()
			delete(sub.super, c)
		}
		for super := range c.super {
			c.removeReference()
			delete(super.sub, c)
		}
		delete(store.classes, class)
	}
}

func (store *Store) deleteProperty(property quad.Value) {
	if p, ok := store.properties[property]; ok {
		for super := range p.super {
			p.removeReference()
			delete(super.sub, p)
		}
		for sub := range p.sub {
			p.removeReference()
			delete(sub.super, p)
		}
		delete(store.properties, property)
	}
}

func (store *Store) deleteClassRelationship(child quad.Value, parent quad.Value) {
	parentClass := store.GetClass(parent)
	childClass := store.GetClass(child)
	if _, ok := parentClass.sub[childClass]; ok {
		parentClass.removeReference()
		delete(parentClass.sub, childClass)
		childClass.removeReference()
		delete(childClass.super, parentClass)
	}
}

func (store *Store) deletePropertyRelationship(child quad.Value, parent quad.Value) {
	parentProperty := store.GetProperty(parent)
	childProperty := store.GetProperty(child)
	if _, ok := parentProperty.sub[childProperty]; ok {
		parentProperty.removeReference()
		delete(parentProperty.sub, childProperty)
		childProperty.removeReference()
		delete(childProperty.super, parentProperty)
	}
}

func (store *Store) unsetPropertyDomain(property quad.Value, domain quad.Value) {
	p := store.GetProperty(property)
	class := store.GetClass(domain)
	// FIXME(iddan): Currently doesn't support multiple domains as they are very rare
	p.domain = nil
	delete(class.ownProperties, p)
	p.removeReference()
	class.removeReference()
}

func (store *Store) unsetPropertyRange(property quad.Value, _range quad.Value) {
	p := store.GetProperty(property)
	class := store.GetClass(_range)
	p._range = nil
	// FIXME(iddan): Currently doesn't support multiple ranges as they are very rare
	delete(class.inProperties, p)
	p.removeReference()
	class.removeReference()
}

// UnprocessQuad is used to delete a quad from the store
func (store *Store) UnprocessQuad(q quad.Quad) {
	subject, predicate, object := q.Subject, q.Predicate, q.Object
	predicateIRI, ok := predicate.(quad.IRI)
	if !ok {
		return
	}
	switch predicateIRI {
	case rdf.Type:
		objectIRI, ok := object.(quad.IRI)
		if !ok {
			return
		}
		switch objectIRI {
		case rdfs.Class:
			store.deleteClass(subject)
		case rdf.Property:
			store.deleteProperty(subject)
		default:
			store.deleteClass(object)
		}
	case rdfs.SubPropertyOf:
		store.deletePropertyRelationship(subject, object)
	case rdfs.SubClassOf:
		store.deleteClassRelationship(subject, object)
	case rdfs.Domain:
		store.unsetPropertyDomain(subject, object)
	case rdfs.Range:
		store.unsetPropertyRange(subject, object)
	default:
		store.deleteProperty(predicate)
	}
}

// UnprocessQuads is used to delete multiple quads from the store
func (store *Store) UnprocessQuads(quads []quad.Quad) {
	for _, q := range quads {
		store.UnprocessQuad(q)
	}
}
<|endoftext|>


<commit_before>package middleware

import (
	"github.com/afex/hystrix-go/hystrix"
	"github.com/gin-gonic/gin"
	"strings"

	"github.com/eirka/eirka-libs/redis"
)

var (
	RedisKeyIndex = make(map[string]RedisKey)
	RedisKeys     = []RedisKey{
		{base: "index", fieldcount: 1, hash: true, expire: false},
		{base: "thread", fieldcount: 2, hash: true, expire: false},
		{base: "tag", fieldcount: 2, hash: true, expire: true},
		{base: "image", fieldcount: 1, hash: true, expire: false},
		{base: "post", fieldcount: 2, hash: true, expire: false},
		{base: "tags", fieldcount: 1, hash: true, expire: false},
		{base: "directory", fieldcount: 1, hash: true, expire: false},
		{base: "new", fieldcount: 1, hash: false, expire: true},
		{base: "popular", fieldcount: 1, hash: false, expire: true},
		{base: "favorited", fieldcount: 1, hash: false, expire: true},
		{base: "tagtypes", fieldcount: 0, hash: false, expire: false},
		{base: "imageboards", fieldcount: 0, hash: false, expire: true},
	}
)

func init() {
	// key index map
	for _, key := range RedisKeys {
		RedisKeyIndex[key.base] = key
	}
}

// Cache will check for the key in Redis and serve it. If not found, it will
// take the marshalled JSON from the controller and set it in Redis
func Cache() gin.HandlerFunc {
	return func(c *gin.Context) {
		var result []byte
		var err error

		// bool for analytics middleware
		c.Set("cached", false)

		// break cache if there is a query
		if c.Request.URL.RawQuery != "" {
			c.Next()
			return
		}

		// redis circuitbreaker
		err = hystrix.Do("cache", func() (err error) {

			// Trim leading / from path and split
			params := strings.Split(strings.Trim(c.Request.URL.Path, "/"), "/")

			// get the keyname
			key, ok := RedisKeyIndex[params[0]]
			if !ok {
				c.Next()
				return
			}

			// set the key minus the base
			key.SetKey(params[1:]...)

			result, err = key.Get()
			if err == redis.ErrCacheMiss {
				// go to the controller
				c.Next()

				// Check if there was an error from the controller
				_, controllerError := c.Get("controllerError")
				if controllerError {
					c.Abort()
					return
				}

				err = key.Set(c.MustGet("data").([]byte))
				if err != nil {
					c.Error(err)
					c.Abort()
					return
				}

			} else if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

			return

		}, func(e error) (err error) {
			c.Next()
			return
		})

		// if we made it this far then the page was cached
		c.Set("cached", true)

		c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Write(result)
		c.Abort()
		return
	}

}

type RedisKey struct {
	base       string
	fieldcount int
	hash       bool
	expire     bool
	key        string
	hashid     string
}

func (r *RedisKey) SetKey(ids ...string) {

	if r.fieldcount == 0 {
		r.key = r.base
		return
	}

	// create our key
	r.key = strings.Join([]string{r.base, strings.Join(ids[:r.fieldcount], ":")}, ":")

	// get our hash id
	if r.hash {
		r.hashid = strings.Join(ids[r.fieldcount:], "")
	}

	return
}

func (r *RedisKey) Get() (result []byte, err error) {

	if r.hash {
		return redis.RedisCache.HGet(r.key, r.hashid)
	} else {
		return redis.RedisCache.Get(r.key)
	}

	return
}

func (r *RedisKey) Set(data []byte) (err error) {

	if r.hash {
		err = redis.RedisCache.HMSet(r.key, r.hashid, data)
	} else {
		err = redis.RedisCache.Set(r.key, data)
	}

	if r.expire {
		return redis.RedisCache.Expire(r.key, 600)
	}

	return
}
<commit_msg>try hystrix on cache middleware<commit_after>package middleware

import (
	"github.com/afex/hystrix-go/hystrix"
	"github.com/gin-gonic/gin"
	"strings"

	"github.com/eirka/eirka-libs/redis"
)

var (
	RedisKeyIndex = make(map[string]RedisKey)
	RedisKeys     = []RedisKey{
		{base: "index", fieldcount: 1, hash: true, expire: false},
		{base: "thread", fieldcount: 2, hash: true, expire: false},
		{base: "tag", fieldcount: 2, hash: true, expire: true},
		{base: "image", fieldcount: 1, hash: true, expire: false},
		{base: "post", fieldcount: 2, hash: true, expire: false},
		{base: "tags", fieldcount: 1, hash: true, expire: false},
		{base: "directory", fieldcount: 1, hash: true, expire: false},
		{base: "new", fieldcount: 1, hash: false, expire: true},
		{base: "popular", fieldcount: 1, hash: false, expire: true},
		{base: "favorited", fieldcount: 1, hash: false, expire: true},
		{base: "tagtypes", fieldcount: 0, hash: false, expire: false},
		{base: "imageboards", fieldcount: 0, hash: false, expire: true},
	}
)

func init() {
	// key index map
	for _, key := range RedisKeys {
		RedisKeyIndex[key.base] = key
	}
}

// Cache will check for the key in Redis and serve it. If not found, it will
// take the marshalled JSON from the controller and set it in Redis
func Cache() gin.HandlerFunc {
	return func(c *gin.Context) {
		var result []byte
		var err error

		// bool for analytics middleware
		c.Set("cached", false)

		// break cache if there is a query
		if c.Request.URL.RawQuery != "" {
			c.Next()
			return
		}

		// redis circuitbreaker
		err = hystrix.Do("cache", func() (err error) {

			// Trim leading / from path and split
			params := strings.Split(strings.Trim(c.Request.URL.Path, "/"), "/")

			// get the keyname
			key, ok := RedisKeyIndex[params[0]]
			if !ok {
				c.Next()
				return
			}

			// set the key minus the base
			key.SetKey(params[1:]...)

			result, err = key.Get()
			if err == redis.ErrCacheMiss {
				// go to the controller
				c.Next()

				// Check if there was an error from the controller
				_, controllerError := c.Get("controllerError")
				if controllerError {
					c.Abort()
					return
				}

				err = key.Set(c.MustGet("data").([]byte))
				if err != nil {
					c.Error(err)
					c.Abort()
					return
				}

			} else if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

			return

		}, func(err error) error {
			c.Next()
			return nil
		})

		// if we made it this far then the page was cached
		c.Set("cached", true)

		c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Write(result)
		c.Abort()
		return
	}

}

type RedisKey struct {
	base       string
	fieldcount int
	hash       bool
	expire     bool
	key        string
	hashid     string
}

func (r *RedisKey) SetKey(ids ...string) {

	if r.fieldcount == 0 {
		r.key = r.base
		return
	}

	// create our key
	r.key = strings.Join([]string{r.base, strings.Join(ids[:r.fieldcount], ":")}, ":")

	// get our hash id
	if r.hash {
		r.hashid = strings.Join(ids[r.fieldcount:], "")
	}

	return
}

func (r *RedisKey) Get() (result []byte, err error) {

	if r.hash {
		return redis.RedisCache.HGet(r.key, r.hashid)
	} else {
		return redis.RedisCache.Get(r.key)
	}

	return
}

func (r *RedisKey) Set(data []byte) (err error) {

	if r.hash {
		err = redis.RedisCache.HMSet(r.key, r.hashid, data)
	} else {
		err = redis.RedisCache.Set(r.key, data)
	}

	if r.expire {
		return redis.RedisCache.Expire(r.key, 600)
	}

	return
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Pagoda Box Inc.
//
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

//
package config

import (
	"errors"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"time"

	"github.com/jcelliott/lumber"

	"github.com/nanobox-io/nanobox-logtap"
	"github.com/nanopack/mist/core"
)

//
var (
	App         string
	LogtapHost  string
	Ports       map[string]string
	IP          string
	MountFolder string
	DockerMount string

	Log        lumber.Logger
	Logtap     *logtap.Logtap
	Mist       *mist.Mist
	LogHandler http.HandlerFunc
)

//
func init() {
	MountFolder = "/vagrant/"
	DockerMount = "/mnt/"
	// create an error object
	var err error

	Log = lumber.NewConsoleLogger(lumber.INFO)

	//
	Ports = map[string]string{
		"api":    ":1757",
		"logtap": ":514",
		"mist":   ":1445",
		"router": "60000",
	}

	IP, err = externalIP()
	if err != nil {
		Log.Error("error: %s\n", err.Error())
	}

	LogtapHost = IP

	App, err = AppName()
	if err != nil {
		Log.Error("config error %s\n", err.Error())
	}

	Mist = mist.New()
	Logtap = logtap.New(Log)
}

//
func externalIP() (string, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return "", err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return "", err
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			if strings.HasPrefix(ip.String(), "10") {
				continue
			}
			return ip.String(), nil
		}
	}
	return "", errors.New("are you connected to the network?")
}

//
func AppName() (name string, e error) {
	for i := 0; i < 100; i++ {
		files, err := ioutil.ReadDir(MountFolder + "code/")
		if err != nil {
			<-time.After(time.Second)
			e = err
			continue
		}

		if len(files) < 1 || !files[0].IsDir() {
			<-time.After(time.Second)
			e = errors.New("There is no code in your " + MountFolder + "code/ folder")
			continue
		}
		name = files[0].Name()
		e = nil
		break
	}
	return
}
<commit_msg>change logging so i can see the travis ci error<commit_after>// Copyright (c) 2014 Pagoda Box Inc.
//
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

//
package config

import (
	"errors"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"time"

	"github.com/jcelliott/lumber"

	"github.com/nanobox-io/nanobox-logtap"
	"github.com/nanopack/mist/core"
)

//
var (
	App         string
	LogtapHost  string
	Ports       map[string]string
	IP          string
	MountFolder string
	DockerMount string

	Log        lumber.Logger
	Logtap     *logtap.Logtap
	Mist       *mist.Mist
	LogHandler http.HandlerFunc
)

//
func init() {
	MountFolder = "/vagrant/"
	DockerMount = "/mnt/"
	// create an error object
	var err error

	Log = lumber.NewConsoleLogger(lumber.DEBUG)

	//
	Ports = map[string]string{
		"api":    ":1757",
		"logtap": ":514",
		"mist":   ":1445",
		"router": "60000",
	}

	IP, err = externalIP()
	if err != nil {
		Log.Error("error: %s\n", err.Error())
	}

	LogtapHost = IP

	App, err = AppName()
	if err != nil {
		Log.Error("config error %s\n", err.Error())
	}

	Mist = mist.New()
	Logtap = logtap.New(Log)
}

//
func externalIP() (string, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return "", err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return "", err
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			if strings.HasPrefix(ip.String(), "10") {
				continue
			}
			return ip.String(), nil
		}
	}
	return "", errors.New("are you connected to the network?")
}

//
func AppName() (name string, e error) {
	for i := 0; i < 100; i++ {
		files, err := ioutil.ReadDir(MountFolder + "code/")
		if err != nil {
			<-time.After(time.Second)
			e = err
			continue
		}

		if len(files) < 1 || !files[0].IsDir() {
			<-time.After(time.Second)
			e = errors.New("There is no code in your " + MountFolder + "code/ folder")
			continue
		}
		name = files[0].Name()
		e = nil
		break
	}
	return
}
<|endoftext|>