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 }