github.com/xrash/gopher-lua@v0.0.0-20160304065408-e5faab4db06a/utils.go (about) 1 package lua 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "strconv" 8 "strings" 9 "time" 10 ) 11 12 func intMin(a, b int) int { 13 if a < b { 14 return a 15 } else { 16 return b 17 } 18 } 19 20 func intMax(a, b int) int { 21 if a > b { 22 return a 23 } else { 24 return b 25 } 26 } 27 28 func defaultFormat(v interface{}, f fmt.State, c rune) { 29 buf := make([]string, 0, 10) 30 buf = append(buf, "%") 31 for i := 0; i < 128; i++ { 32 if f.Flag(i) { 33 buf = append(buf, string(i)) 34 } 35 } 36 37 if w, ok := f.Width(); ok { 38 buf = append(buf, strconv.Itoa(w)) 39 } 40 if p, ok := f.Precision(); ok { 41 buf = append(buf, "."+strconv.Itoa(p)) 42 } 43 buf = append(buf, string(c)) 44 format := strings.Join(buf, "") 45 fmt.Fprintf(f, format, v) 46 } 47 48 type flagScanner struct { 49 flag byte 50 start string 51 end string 52 buf []byte 53 str string 54 Length int 55 Pos int 56 HasFlag bool 57 ChangeFlag bool 58 } 59 60 func newFlagScanner(flag byte, start, end, str string) *flagScanner { 61 return &flagScanner{flag, start, end, make([]byte, 0, len(str)), str, len(str), 0, false, false} 62 } 63 64 func (fs *flagScanner) AppendString(str string) { fs.buf = append(fs.buf, str...) } 65 66 func (fs *flagScanner) AppendChar(ch byte) { fs.buf = append(fs.buf, ch) } 67 68 func (fs *flagScanner) String() string { return string(fs.buf) } 69 70 func (fs *flagScanner) Next() (byte, bool) { 71 c := byte('\000') 72 fs.ChangeFlag = false 73 if fs.Pos == fs.Length { 74 if fs.HasFlag { 75 fs.AppendString(fs.end) 76 } 77 return c, true 78 } else { 79 c = fs.str[fs.Pos] 80 if c == fs.flag { 81 if fs.Pos < (fs.Length-1) && fs.str[fs.Pos+1] == fs.flag { 82 fs.HasFlag = false 83 fs.AppendChar(fs.flag) 84 fs.Pos += 2 85 return fs.Next() 86 } else if fs.Pos != fs.Length-1 { 87 if fs.HasFlag { 88 fs.AppendString(fs.end) 89 } 90 fs.AppendString(fs.start) 91 fs.ChangeFlag = true 92 fs.HasFlag = true 93 } 94 } 95 } 96 fs.Pos++ 97 return c, false 98 } 99 100 var cDateFlagToGo = map[byte]string{ 101 'a': "mon", 'A': "Monday", 'b': "Jan", 'B': "January", 'c': "02 Jan 06 15:04 MST", 'd': "02", 102 'F': "2006-01-02", 'H': "15", 'I': "03", 'm': "01", 'M': "04", 'p': "PM", 'P': "pm", 'S': "05", 103 'y': "06", 'Y': "2006", 'z': "-0700", 'Z': "MST"} 104 105 func strftime(t time.Time, cfmt string) string { 106 sc := newFlagScanner('%', "", "", cfmt) 107 for c, eos := sc.Next(); !eos; c, eos = sc.Next() { 108 if !sc.ChangeFlag { 109 if sc.HasFlag { 110 if v, ok := cDateFlagToGo[c]; ok { 111 sc.AppendString(t.Format(v)) 112 } else { 113 switch c { 114 case 'w': 115 sc.AppendString(fmt.Sprint(int(t.Weekday()))) 116 default: 117 sc.AppendChar('%') 118 sc.AppendChar(c) 119 } 120 } 121 sc.HasFlag = false 122 } else { 123 sc.AppendChar(c) 124 } 125 } 126 } 127 128 return sc.String() 129 } 130 131 func isInteger(v LNumber) bool { 132 return float64(v) == float64(int64(v)) 133 //_, frac := math.Modf(float64(v)) 134 //return frac == 0.0 135 } 136 137 func isArrayKey(v LNumber) bool { 138 return isInteger(v) && v < LNumber(int((^uint(0))>>1)) && v > LNumber(0) && v < LNumber(MaxArrayIndex) 139 } 140 141 func parseNumber(number string) (LNumber, error) { 142 var value LNumber 143 number = strings.Trim(number, " \t\n") 144 if v, err := strconv.ParseInt(number, 0, LNumberBit); err != nil { 145 if v2, err2 := strconv.ParseFloat(number, LNumberBit); err2 != nil { 146 return LNumber(0), err2 147 } else { 148 value = LNumber(v2) 149 } 150 } else { 151 value = LNumber(v) 152 } 153 return value, nil 154 } 155 156 func popenArgs(arg string) (string, []string) { 157 cmd := "/bin/sh" 158 args := []string{"-c"} 159 if LuaOS == "windows" { 160 cmd = "C:\\Windows\\system32\\cmd.exe" 161 args = []string{"/c"} 162 } 163 args = append(args, arg) 164 return cmd, args 165 } 166 167 func isGoroutineSafe(lv LValue) bool { 168 switch v := lv.(type) { 169 case *LFunction, *LUserData, *LState: 170 return false 171 case *LTable: 172 return v.Metatable == LNil 173 default: 174 return true 175 } 176 } 177 178 func readBufioSize(reader *bufio.Reader, size int64) ([]byte, error, bool) { 179 result := []byte{} 180 read := int64(0) 181 var err error 182 var n int 183 for read != size { 184 buf := make([]byte, size-read) 185 n, err = reader.Read(buf) 186 if err != nil { 187 break 188 } 189 read += int64(n) 190 result = append(result, buf[:n]...) 191 } 192 e := err 193 if e != nil && e == io.EOF { 194 e = nil 195 } 196 197 return result, e, len(result) == 0 && err == io.EOF 198 } 199 200 func readBufioLine(reader *bufio.Reader) ([]byte, error, bool) { 201 result := []byte{} 202 var buf []byte 203 var err error 204 var isprefix bool = true 205 for isprefix { 206 buf, isprefix, err = reader.ReadLine() 207 if err != nil { 208 break 209 } 210 result = append(result, buf...) 211 } 212 e := err 213 if e != nil && e == io.EOF { 214 e = nil 215 } 216 217 return result, e, len(result) == 0 && err == io.EOF 218 } 219 220 func int2Fb(val int) int { 221 e := 0 222 x := val 223 for x >= 16 { 224 x = (x + 1) >> 1 225 e++ 226 } 227 if x < 8 { 228 return x 229 } 230 return ((e + 1) << 3) | (x - 8) 231 } 232 233 func strCmp(s1, s2 string) int { 234 len1 := len(s1) 235 len2 := len(s2) 236 for i := 0; ; i++ { 237 c1 := -1 238 if i < len1 { 239 c1 = int(s1[i]) 240 } 241 c2 := -1 242 if i != len2 { 243 c2 = int(s2[i]) 244 } 245 switch { 246 case c1 < c2: 247 return -1 248 case c1 > c2: 249 return +1 250 case c1 < 0: 251 return 0 252 } 253 } 254 }