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 }