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  }