github.com/astaxie/beego@v1.12.3/orm/utils.go (about)

     1  // Copyright 2014 beego Author. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package orm
    16  
    17  import (
    18  	"fmt"
    19  	"math/big"
    20  	"reflect"
    21  	"strconv"
    22  	"strings"
    23  	"time"
    24  )
    25  
    26  type fn func(string) string
    27  
    28  var (
    29  	nameStrategyMap = map[string]fn{
    30  		defaultNameStrategy:      snakeString,
    31  		SnakeAcronymNameStrategy: snakeStringWithAcronym,
    32  	}
    33  	defaultNameStrategy      = "snakeString"
    34  	SnakeAcronymNameStrategy = "snakeStringWithAcronym"
    35  	nameStrategy             = defaultNameStrategy
    36  )
    37  
    38  // StrTo is the target string
    39  type StrTo string
    40  
    41  // Set string
    42  func (f *StrTo) Set(v string) {
    43  	if v != "" {
    44  		*f = StrTo(v)
    45  	} else {
    46  		f.Clear()
    47  	}
    48  }
    49  
    50  // Clear string
    51  func (f *StrTo) Clear() {
    52  	*f = StrTo(0x1E)
    53  }
    54  
    55  // Exist check string exist
    56  func (f StrTo) Exist() bool {
    57  	return string(f) != string(0x1E)
    58  }
    59  
    60  // Bool string to bool
    61  func (f StrTo) Bool() (bool, error) {
    62  	return strconv.ParseBool(f.String())
    63  }
    64  
    65  // Float32 string to float32
    66  func (f StrTo) Float32() (float32, error) {
    67  	v, err := strconv.ParseFloat(f.String(), 32)
    68  	return float32(v), err
    69  }
    70  
    71  // Float64 string to float64
    72  func (f StrTo) Float64() (float64, error) {
    73  	return strconv.ParseFloat(f.String(), 64)
    74  }
    75  
    76  // Int string to int
    77  func (f StrTo) Int() (int, error) {
    78  	v, err := strconv.ParseInt(f.String(), 10, 32)
    79  	return int(v), err
    80  }
    81  
    82  // Int8 string to int8
    83  func (f StrTo) Int8() (int8, error) {
    84  	v, err := strconv.ParseInt(f.String(), 10, 8)
    85  	return int8(v), err
    86  }
    87  
    88  // Int16 string to int16
    89  func (f StrTo) Int16() (int16, error) {
    90  	v, err := strconv.ParseInt(f.String(), 10, 16)
    91  	return int16(v), err
    92  }
    93  
    94  // Int32 string to int32
    95  func (f StrTo) Int32() (int32, error) {
    96  	v, err := strconv.ParseInt(f.String(), 10, 32)
    97  	return int32(v), err
    98  }
    99  
   100  // Int64 string to int64
   101  func (f StrTo) Int64() (int64, error) {
   102  	v, err := strconv.ParseInt(f.String(), 10, 64)
   103  	if err != nil {
   104  		i := new(big.Int)
   105  		ni, ok := i.SetString(f.String(), 10) // octal
   106  		if !ok {
   107  			return v, err
   108  		}
   109  		return ni.Int64(), nil
   110  	}
   111  	return v, err
   112  }
   113  
   114  // Uint string to uint
   115  func (f StrTo) Uint() (uint, error) {
   116  	v, err := strconv.ParseUint(f.String(), 10, 32)
   117  	return uint(v), err
   118  }
   119  
   120  // Uint8 string to uint8
   121  func (f StrTo) Uint8() (uint8, error) {
   122  	v, err := strconv.ParseUint(f.String(), 10, 8)
   123  	return uint8(v), err
   124  }
   125  
   126  // Uint16 string to uint16
   127  func (f StrTo) Uint16() (uint16, error) {
   128  	v, err := strconv.ParseUint(f.String(), 10, 16)
   129  	return uint16(v), err
   130  }
   131  
   132  // Uint32 string to uint32
   133  func (f StrTo) Uint32() (uint32, error) {
   134  	v, err := strconv.ParseUint(f.String(), 10, 32)
   135  	return uint32(v), err
   136  }
   137  
   138  // Uint64 string to uint64
   139  func (f StrTo) Uint64() (uint64, error) {
   140  	v, err := strconv.ParseUint(f.String(), 10, 64)
   141  	if err != nil {
   142  		i := new(big.Int)
   143  		ni, ok := i.SetString(f.String(), 10)
   144  		if !ok {
   145  			return v, err
   146  		}
   147  		return ni.Uint64(), nil
   148  	}
   149  	return v, err
   150  }
   151  
   152  // String string to string
   153  func (f StrTo) String() string {
   154  	if f.Exist() {
   155  		return string(f)
   156  	}
   157  	return ""
   158  }
   159  
   160  // ToStr interface to string
   161  func ToStr(value interface{}, args ...int) (s string) {
   162  	switch v := value.(type) {
   163  	case bool:
   164  		s = strconv.FormatBool(v)
   165  	case float32:
   166  		s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32))
   167  	case float64:
   168  		s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64))
   169  	case int:
   170  		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
   171  	case int8:
   172  		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
   173  	case int16:
   174  		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
   175  	case int32:
   176  		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
   177  	case int64:
   178  		s = strconv.FormatInt(v, argInt(args).Get(0, 10))
   179  	case uint:
   180  		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
   181  	case uint8:
   182  		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
   183  	case uint16:
   184  		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
   185  	case uint32:
   186  		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
   187  	case uint64:
   188  		s = strconv.FormatUint(v, argInt(args).Get(0, 10))
   189  	case string:
   190  		s = v
   191  	case []byte:
   192  		s = string(v)
   193  	default:
   194  		s = fmt.Sprintf("%v", v)
   195  	}
   196  	return s
   197  }
   198  
   199  // ToInt64 interface to int64
   200  func ToInt64(value interface{}) (d int64) {
   201  	val := reflect.ValueOf(value)
   202  	switch value.(type) {
   203  	case int, int8, int16, int32, int64:
   204  		d = val.Int()
   205  	case uint, uint8, uint16, uint32, uint64:
   206  		d = int64(val.Uint())
   207  	default:
   208  		panic(fmt.Errorf("ToInt64 need numeric not `%T`", value))
   209  	}
   210  	return
   211  }
   212  
   213  func snakeStringWithAcronym(s string) string {
   214  	data := make([]byte, 0, len(s)*2)
   215  	num := len(s)
   216  	for i := 0; i < num; i++ {
   217  		d := s[i]
   218  		before := false
   219  		after := false
   220  		if i > 0 {
   221  			before = s[i-1] >= 'a' && s[i-1] <= 'z'
   222  		}
   223  		if i+1 < num {
   224  			after = s[i+1] >= 'a' && s[i+1] <= 'z'
   225  		}
   226  		if i > 0 && d >= 'A' && d <= 'Z' && (before || after) {
   227  			data = append(data, '_')
   228  		}
   229  		data = append(data, d)
   230  	}
   231  	return strings.ToLower(string(data[:]))
   232  }
   233  
   234  // snake string, XxYy to xx_yy , XxYY to xx_y_y
   235  func snakeString(s string) string {
   236  	data := make([]byte, 0, len(s)*2)
   237  	j := false
   238  	num := len(s)
   239  	for i := 0; i < num; i++ {
   240  		d := s[i]
   241  		if i > 0 && d >= 'A' && d <= 'Z' && j {
   242  			data = append(data, '_')
   243  		}
   244  		if d != '_' {
   245  			j = true
   246  		}
   247  		data = append(data, d)
   248  	}
   249  	return strings.ToLower(string(data[:]))
   250  }
   251  
   252  // SetNameStrategy set different name strategy
   253  func SetNameStrategy(s string) {
   254  	if SnakeAcronymNameStrategy != s {
   255  		nameStrategy = defaultNameStrategy
   256  	}
   257  	nameStrategy = s
   258  }
   259  
   260  // camel string, xx_yy to XxYy
   261  func camelString(s string) string {
   262  	data := make([]byte, 0, len(s))
   263  	flag, num := true, len(s)-1
   264  	for i := 0; i <= num; i++ {
   265  		d := s[i]
   266  		if d == '_' {
   267  			flag = true
   268  			continue
   269  		} else if flag {
   270  			if d >= 'a' && d <= 'z' {
   271  				d = d - 32
   272  			}
   273  			flag = false
   274  		}
   275  		data = append(data, d)
   276  	}
   277  	return string(data[:])
   278  }
   279  
   280  type argString []string
   281  
   282  // get string by index from string slice
   283  func (a argString) Get(i int, args ...string) (r string) {
   284  	if i >= 0 && i < len(a) {
   285  		r = a[i]
   286  	} else if len(args) > 0 {
   287  		r = args[0]
   288  	}
   289  	return
   290  }
   291  
   292  type argInt []int
   293  
   294  // get int by index from int slice
   295  func (a argInt) Get(i int, args ...int) (r int) {
   296  	if i >= 0 && i < len(a) {
   297  		r = a[i]
   298  	}
   299  	if len(args) > 0 {
   300  		r = args[0]
   301  	}
   302  	return
   303  }
   304  
   305  // parse time to string with location
   306  func timeParse(dateString, format string) (time.Time, error) {
   307  	tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc)
   308  	return tp, err
   309  }
   310  
   311  // get pointer indirect type
   312  func indirectType(v reflect.Type) reflect.Type {
   313  	switch v.Kind() {
   314  	case reflect.Ptr:
   315  		return indirectType(v.Elem())
   316  	default:
   317  		return v
   318  	}
   319  }