1// Copyright 2017 The Gitea Authors. All rights reserved. 2// Use of this source code is governed by a MIT-style 3// license that can be found in the LICENSE file. 4 5package util 6 7import ( 8 "bytes" 9 "crypto/rand" 10 "errors" 11 "math/big" 12 "strconv" 13 "strings" 14) 15 16// OptionalBool a boolean that can be "null" 17type OptionalBool byte 18 19const ( 20 // OptionalBoolNone a "null" boolean value 21 OptionalBoolNone OptionalBool = iota 22 // OptionalBoolTrue a "true" boolean value 23 OptionalBoolTrue 24 // OptionalBoolFalse a "false" boolean value 25 OptionalBoolFalse 26) 27 28// IsTrue return true if equal to OptionalBoolTrue 29func (o OptionalBool) IsTrue() bool { 30 return o == OptionalBoolTrue 31} 32 33// IsFalse return true if equal to OptionalBoolFalse 34func (o OptionalBool) IsFalse() bool { 35 return o == OptionalBoolFalse 36} 37 38// IsNone return true if equal to OptionalBoolNone 39func (o OptionalBool) IsNone() bool { 40 return o == OptionalBoolNone 41} 42 43// OptionalBoolOf get the corresponding OptionalBool of a bool 44func OptionalBoolOf(b bool) OptionalBool { 45 if b { 46 return OptionalBoolTrue 47 } 48 return OptionalBoolFalse 49} 50 51// OptionalBoolParse get the corresponding OptionalBool of a string using strconv.ParseBool 52func OptionalBoolParse(s string) OptionalBool { 53 b, e := strconv.ParseBool(s) 54 if e != nil { 55 return OptionalBoolNone 56 } 57 return OptionalBoolOf(b) 58} 59 60// Max max of two ints 61func Max(a, b int) int { 62 if a < b { 63 return b 64 } 65 return a 66} 67 68// Min min of two ints 69func Min(a, b int) int { 70 if a > b { 71 return b 72 } 73 return a 74} 75 76// IsEmptyString checks if the provided string is empty 77func IsEmptyString(s string) bool { 78 return len(strings.TrimSpace(s)) == 0 79} 80 81// NormalizeEOL will convert Windows (CRLF) and Mac (CR) EOLs to UNIX (LF) 82func NormalizeEOL(input []byte) []byte { 83 var right, left, pos int 84 if right = bytes.IndexByte(input, '\r'); right == -1 { 85 return input 86 } 87 length := len(input) 88 tmp := make([]byte, length) 89 90 // We know that left < length because otherwise right would be -1 from IndexByte. 91 copy(tmp[pos:pos+right], input[left:left+right]) 92 pos += right 93 tmp[pos] = '\n' 94 left += right + 1 95 pos++ 96 97 for left < length { 98 if input[left] == '\n' { 99 left++ 100 } 101 102 right = bytes.IndexByte(input[left:], '\r') 103 if right == -1 { 104 copy(tmp[pos:], input[left:]) 105 pos += length - left 106 break 107 } 108 copy(tmp[pos:pos+right], input[left:left+right]) 109 pos += right 110 tmp[pos] = '\n' 111 left += right + 1 112 pos++ 113 } 114 return tmp[:pos] 115} 116 117// MergeInto merges pairs of values into a "dict" 118func MergeInto(dict map[string]interface{}, values ...interface{}) (map[string]interface{}, error) { 119 for i := 0; i < len(values); i++ { 120 switch key := values[i].(type) { 121 case string: 122 i++ 123 if i == len(values) { 124 return nil, errors.New("specify the key for non array values") 125 } 126 dict[key] = values[i] 127 case map[string]interface{}: 128 m := values[i].(map[string]interface{}) 129 for i, v := range m { 130 dict[i] = v 131 } 132 default: 133 return nil, errors.New("dict values must be maps") 134 } 135 } 136 137 return dict, nil 138} 139 140// RandomInt returns a random integer between 0 and limit, inclusive 141func RandomInt(limit int64) (int64, error) { 142 rInt, err := rand.Int(rand.Reader, big.NewInt(limit)) 143 if err != nil { 144 return 0, err 145 } 146 return rInt.Int64(), nil 147} 148 149const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" 150 151// RandomString generates a random alphanumerical string 152func RandomString(length int64) (string, error) { 153 bytes := make([]byte, length) 154 limit := int64(len(letters)) 155 for i := range bytes { 156 num, err := RandomInt(limit) 157 if err != nil { 158 return "", err 159 } 160 bytes[i] = letters[num] 161 } 162 return string(bytes), nil 163} 164 165// RandomBytes generates `length` bytes 166// This differs from RandomString, as RandomString is limits each byte to have 167// a maximum value of 63 instead of 255(max byte size) 168func RandomBytes(length int64) ([]byte, error) { 169 bytes := make([]byte, length) 170 _, err := rand.Read(bytes) 171 return bytes, err 172} 173