github.com/shawnclovie/gopher-lua@v0.0.0-20200520092726-90b44ec0e2f2/utils.go (about)

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