package lua import ( "bufio" "fmt" "io" "reflect" "strconv" "strings" "time" "unsafe" ) func intMin(a, b int) int { if a < b { return a } else { return b } } func intMax(a, b int) int { if a > b { return a } else { return b } } func defaultFormat(v interface{}, f fmt.State, c rune) { buf := make([]string, 0, 10) buf = append(buf, "%") for i := 0; i < 128; i++ { if f.Flag(i) { buf = append(buf, string(i)) } } if w, ok := f.Width(); ok { buf = append(buf, strconv.Itoa(w)) } if p, ok := f.Precision(); ok { buf = append(buf, "."+strconv.Itoa(p)) } buf = append(buf, string(c)) format := strings.Join(buf, "") fmt.Fprintf(f, format, v) } type flagScanner struct { flag byte start string end string buf []byte str string Length int Pos int HasFlag bool ChangeFlag bool } func newFlagScanner(flag byte, start, end, str string) *flagScanner { return &flagScanner{flag, start, end, make([]byte, 0, len(str)), str, len(str), 0, false, false} } func (fs *flagScanner) AppendString(str string) { fs.buf = append(fs.buf, str...) } func (fs *flagScanner) AppendChar(ch byte) { fs.buf = append(fs.buf, ch) } func (fs *flagScanner) String() string { return string(fs.buf) } func (fs *flagScanner) Next() (byte, bool) { c := byte('\000') fs.ChangeFlag = false if fs.Pos == fs.Length { if fs.HasFlag { fs.AppendString(fs.end) } return c, true } else { c = fs.str[fs.Pos] if c == fs.flag { if fs.Pos < (fs.Length-1) && fs.str[fs.Pos+1] == fs.flag { fs.HasFlag = false fs.AppendChar(fs.flag) fs.Pos += 2 return fs.Next() } else if fs.Pos != fs.Length-1 { if fs.HasFlag { fs.AppendString(fs.end) } fs.AppendString(fs.start) fs.ChangeFlag = true fs.HasFlag = true } } } fs.Pos++ return c, false } var cDateFlagToGo = map[byte]string{ 'a': "mon", 'A': "Monday", 'b': "Jan", 'B': "January", 'c': "02 Jan 06 15:04 MST", 'd': "02", 'F': "2006-01-02", 'H': "15", 'I': "03", 'm': "01", 'M': "04", 'p': "PM", 'P': "pm", 'S': "05", 'x': "15/04/05", 'X': "15:04:05", 'y': "06", 'Y': "2006", 'z': "-0700", 'Z': "MST"} func strftime(t time.Time, cfmt string) string { sc := newFlagScanner('%', "", "", cfmt) for c, eos := sc.Next(); !eos; c, eos = sc.Next() { if !sc.ChangeFlag { if sc.HasFlag { if v, ok := cDateFlagToGo[c]; ok { sc.AppendString(t.Format(v)) } else { switch c { case 'w': sc.AppendString(fmt.Sprint(int(t.Weekday()))) default: sc.AppendChar('%') sc.AppendChar(c) } } sc.HasFlag = false } else { sc.AppendChar(c) } } } return sc.String() } func isInteger(v LNumber) bool { return float64(v) == float64(int64(v)) //_, frac := math.Modf(float64(v)) //return frac == 0.0 } func isArrayKey(v LNumber) bool { return isInteger(v) && v < LNumber(int((^uint(0))>>1)) && v > LNumber(0) && v < LNumber(MaxArrayIndex) } func parseNumber(number string) (LNumber, error) { var value LNumber number = strings.Trim(number, " \t\n") if v, err := strconv.ParseInt(number, 0, LNumberBit); err != nil { if v2, err2 := strconv.ParseFloat(number, LNumberBit); err2 != nil { return LNumber(0), err2 } else { value = LNumber(v2) } } else { value = LNumber(v) } return value, nil } func popenArgs(arg string) (string, []string) { cmd := "/bin/sh" args := []string{"-c"} if LuaOS == "windows" { cmd = "C:\\Windows\\system32\\cmd.exe" args = []string{"/c"} } args = append(args, arg) return cmd, args } func isGoroutineSafe(lv LValue) bool { switch v := lv.(type) { case *LFunction, *LUserData, *LState: return false case *LTable: return v.Metatable == LNil default: return true } } func readBufioSize(reader *bufio.Reader, size int64) ([]byte, error, bool) { result := []byte{} read := int64(0) var err error var n int for read != size { buf := make([]byte, size-read) n, err = reader.Read(buf) if err != nil { break } read += int64(n) result = append(result, buf[:n]...) } e := err if e != nil && e == io.EOF { e = nil } return result, e, len(result) == 0 && err == io.EOF } func readBufioLine(reader *bufio.Reader) ([]byte, error, bool) { result := []byte{} var buf []byte var err error var isprefix bool = true for isprefix { buf, isprefix, err = reader.ReadLine() if err != nil { break } result = append(result, buf...) } e := err if e != nil && e == io.EOF { e = nil } return result, e, len(result) == 0 && err == io.EOF } func int2Fb(val int) int { e := 0 x := val for x >= 16 { x = (x + 1) >> 1 e++ } if x < 8 { return x } return ((e + 1) << 3) | (x - 8) } func strCmp(s1, s2 string) int { len1 := len(s1) len2 := len(s2) for i := 0; ; i++ { c1 := -1 if i < len1 { c1 = int(s1[i]) } c2 := -1 if i != len2 { c2 = int(s2[i]) } switch { case c1 < c2: return -1 case c1 > c2: return +1 case c1 < 0: return 0 } } } func unsafeFastStringToReadOnlyBytes(s string) []byte { sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) bh := reflect.SliceHeader{sh.Data, sh.Len, sh.Len} return *(*[]byte)(unsafe.Pointer(&bh)) }