Files
gf/g/util/gconv/gconv.go
2019-06-03 23:53:59 +08:00

402 lines
10 KiB
Go

// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
// Package gconv implements powerful and easy-to-use converting functionality for any types of variables.
package gconv
import (
"encoding/json"
"github.com/gogf/gf/g/encoding/gbinary"
"reflect"
"strconv"
"strings"
)
// Type assert api for String().
type apiString interface {
String() string
}
// Type assert api for Error().
type apiError interface {
Error() string
}
var (
// Empty strings.
emptyStringMap = map[string]struct{}{
"" : struct {}{},
"0" : struct {}{},
"off" : struct {}{},
"false" : struct {}{},
}
)
// Convert converts the variable <i> to the type <t>, the type <t> is specified by string.
// The unnecessary parameter <params> is used for additional parameter passing.
func Convert(i interface{}, t string, params...interface{}) interface{} {
switch t {
case "int": return Int(i)
case "int8": return Int8(i)
case "int16": return Int16(i)
case "int32": return Int32(i)
case "int64": return Int64(i)
case "uint": return Uint(i)
case "uint8": return Uint8(i)
case "uint16": return Uint16(i)
case "uint32": return Uint32(i)
case "uint64": return Uint64(i)
case "float32": return Float32(i)
case "float64": return Float64(i)
case "bool": return Bool(i)
case "string": return String(i)
case "[]byte": return Bytes(i)
case "[]int": return Ints(i)
case "[]string": return Strings(i)
case "Time", "time.Time":
if len(params) > 0 {
return Time(i, String(params[0]))
}
return Time(i)
case "gtime.Time":
if len(params) > 0 {
return GTime(i, String(params[0]))
}
return *GTime(i)
case "GTime", "*gtime.Time":
if len(params) > 0 {
return GTime(i, String(params[0]))
}
return GTime(i)
case "Duration", "time.Duration":
return Duration(i)
default:
return i
}
}
// Byte converts <i> to byte.
func Byte(i interface{}) byte {
if v, ok := i.(byte); ok {
return v
}
return byte(Uint8(i))
}
// Bytes converts <i> to []byte.
func Bytes(i interface{}) []byte {
if i == nil {
return nil
}
switch value := i.(type) {
case string: return []byte(value)
case []byte: return value
default:
return gbinary.Encode(i)
}
}
// Rune converts <i> to rune.
func Rune(i interface{}) rune {
if v, ok := i.(rune); ok {
return v
}
return rune(Int32(i))
}
// Runes converts <i> to []rune.
func Runes(i interface{}) []rune {
if v, ok := i.([]rune); ok {
return v
}
return []rune(String(i))
}
// String converts <i> to string.
func String(i interface{}) string {
if i == nil {
return ""
}
switch value := i.(type) {
case int: return strconv.FormatInt(int64(value), 10)
case int8: return strconv.Itoa(int(value))
case int16: return strconv.Itoa(int(value))
case int32: return strconv.Itoa(int(value))
case int64: return strconv.FormatInt(int64(value), 10)
case uint: return strconv.FormatUint(uint64(value), 10)
case uint8: return strconv.FormatUint(uint64(value), 10)
case uint16: return strconv.FormatUint(uint64(value), 10)
case uint32: return strconv.FormatUint(uint64(value), 10)
case uint64: return strconv.FormatUint(uint64(value), 10)
case float32: return strconv.FormatFloat(float64(value), 'f', -1, 32)
case float64: return strconv.FormatFloat(value, 'f', -1, 64)
case bool: return strconv.FormatBool(value)
case string: return value
case []byte: return string(value)
case []rune: return string(value)
default:
if f, ok := value.(apiString); ok {
// If the variable implements the String() interface,
// then use that interface to perform the conversion
return f.String()
} else if f, ok := value.(apiError); ok {
// If the variable implements the Error() interface,
// then use that interface to perform the conversion
return f.Error()
} else {
// Finally we use json.Marshal to convert.
jsonContent, _ := json.Marshal(value)
return string(jsonContent)
}
}
}
// Bool converts <i> to bool.
// It returns false if <i> is: false, "", 0, "false", "off", empty slice/map.
func Bool(i interface{}) bool {
if i == nil {
return false
}
if v, ok := i.(bool); ok {
return v
}
if s, ok := i.(string); ok {
if _, ok := emptyStringMap[s]; ok {
return false
}
return true
}
rv := reflect.ValueOf(i)
switch rv.Kind() {
case reflect.Ptr: return !rv.IsNil()
case reflect.Map: fallthrough
case reflect.Array: fallthrough
case reflect.Slice: return rv.Len() != 0
case reflect.Struct: return true
default:
s := String(i)
if _, ok := emptyStringMap[s]; ok {
return false
}
return true
}
}
// Int converts <i> to int.
func Int(i interface{}) int {
if i == nil {
return 0
}
if v, ok := i.(int); ok {
return v
}
return int(Int64(i))
}
// Int8 converts <i> to int8.
func Int8(i interface{}) int8 {
if i == nil {
return 0
}
if v, ok := i.(int8); ok {
return v
}
return int8(Int64(i))
}
// Int16 converts <i> to int16.
func Int16(i interface{}) int16 {
if i == nil {
return 0
}
if v, ok := i.(int16); ok {
return v
}
return int16(Int64(i))
}
// Int32 converts <i> to int32.
func Int32(i interface{}) int32 {
if i == nil {
return 0
}
if v, ok := i.(int32); ok {
return v
}
return int32(Int64(i))
}
// Int64 converts <i> to int64.
func Int64(i interface{}) int64 {
if i == nil {
return 0
}
if v, ok := i.(int64); ok {
return v
}
switch value := i.(type) {
case int: return int64(value)
case int8: return int64(value)
case int16: return int64(value)
case int32: return int64(value)
case int64: return value
case uint: return int64(value)
case uint8: return int64(value)
case uint16: return int64(value)
case uint32: return int64(value)
case uint64: return int64(value)
case float32: return int64(value)
case float64: return int64(value)
case bool:
if value {
return 1
}
return 0
default:
s := String(value)
// Hexadecimal
if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') {
if v, e := strconv.ParseInt(s[2 : ], 16, 64); e == nil {
return v
}
}
// Octal
if len(s) > 1 && s[0] == '0' {
if v, e := strconv.ParseInt(s[1 : ], 8, 64); e == nil {
return v
}
}
// Decimal
if v, e := strconv.ParseInt(s, 10, 64); e == nil {
return v
}
// Float64
return int64(Float64(value))
}
}
// Uint converts <i> to uint.
func Uint(i interface{}) uint {
if i == nil {
return 0
}
if v, ok := i.(uint); ok {
return v
}
return uint(Uint64(i))
}
// Uint8 converts <i> to uint8.
func Uint8(i interface{}) uint8 {
if i == nil {
return 0
}
if v, ok := i.(uint8); ok {
return v
}
return uint8(Uint64(i))
}
// Uint16 converts <i> to uint16.
func Uint16(i interface{}) uint16 {
if i == nil {
return 0
}
if v, ok := i.(uint16); ok {
return v
}
return uint16(Uint64(i))
}
// Uint32 converts <i> to uint32.
func Uint32(i interface{}) uint32 {
if i == nil {
return 0
}
if v, ok := i.(uint32); ok {
return v
}
return uint32(Uint64(i))
}
// Uint64 converts <i> to uint64.
func Uint64(i interface{}) uint64 {
if i == nil {
return 0
}
switch value := i.(type) {
case int: return uint64(value)
case int8: return uint64(value)
case int16: return uint64(value)
case int32: return uint64(value)
case int64: return uint64(value)
case uint: return uint64(value)
case uint8: return uint64(value)
case uint16: return uint64(value)
case uint32: return uint64(value)
case uint64: return value
case float32: return uint64(value)
case float64: return uint64(value)
case bool:
if value {
return 1
}
return 0
default:
s := String(value)
// Hexadecimal
if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') {
if v, e := strconv.ParseUint(s[2 : ], 16, 64); e == nil {
return v
}
}
// Octal
if len(s) > 1 && s[0] == '0' {
if v, e := strconv.ParseUint(s[1 : ], 8, 64); e == nil {
return v
}
}
// Decimal
if v, e := strconv.ParseUint(s, 10, 64); e == nil {
return v
}
// Float64
return uint64(Float64(value))
}
}
// Float32 converts <i> to float32.
func Float32 (i interface{}) float32 {
if i == nil {
return 0
}
if v, ok := i.(float32); ok {
return v
}
v, _ := strconv.ParseFloat(strings.TrimSpace(String(i)), 64)
return float32(v)
}
// Float64 converts <i> to float64.
func Float64 (i interface{}) float64 {
if i == nil {
return 0
}
if v, ok := i.(float64); ok {
return v
}
v, _ := strconv.ParseFloat(strings.TrimSpace(String(i)), 64)
return v
}