github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/databases/orm/utils.go (about)

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