github.com/cathalgarvey/gopher-lua@v0.0.0-20160120144859-d37748000dc5/utils.go (about)

     1  package lua
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"math"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  )
    12  
    13  func intMin(a, b int) int {
    14  	if a < b {
    15  		return a
    16  	} else {
    17  		return b
    18  	}
    19  }
    20  
    21  func intMax(a, b int) int {
    22  	if a > b {
    23  		return a
    24  	} else {
    25  		return b
    26  	}
    27  }
    28  
    29  func defaultFormat(v interface{}, f fmt.State, c rune) {
    30  	buf := make([]string, 0, 10)
    31  	buf = append(buf, "%")
    32  	for i := 0; i < 128; i++ {
    33  		if f.Flag(i) {
    34  			buf = append(buf, string(i))
    35  		}
    36  	}
    37  
    38  	if w, ok := f.Width(); ok {
    39  		buf = append(buf, strconv.Itoa(w))
    40  	}
    41  	if p, ok := f.Precision(); ok {
    42  		buf = append(buf, "."+strconv.Itoa(p))
    43  	}
    44  	buf = append(buf, string(c))
    45  	format := strings.Join(buf, "")
    46  	fmt.Fprintf(f, format, v)
    47  }
    48  
    49  type flagScanner struct {
    50  	flag       byte
    51  	start      string
    52  	end        string
    53  	buf        []byte
    54  	str        string
    55  	Length     int
    56  	Pos        int
    57  	HasFlag    bool
    58  	ChangeFlag bool
    59  }
    60  
    61  func newFlagScanner(flag byte, start, end, str string) *flagScanner {
    62  	return &flagScanner{flag, start, end, make([]byte, 0, len(str)), str, len(str), 0, false, false}
    63  }
    64  
    65  func (fs *flagScanner) AppendString(str string) { fs.buf = append(fs.buf, str...) }
    66  
    67  func (fs *flagScanner) AppendChar(ch byte) { fs.buf = append(fs.buf, ch) }
    68  
    69  func (fs *flagScanner) String() string { return string(fs.buf) }
    70  
    71  func (fs *flagScanner) Next() (byte, bool) {
    72  	c := byte('\000')
    73  	fs.ChangeFlag = false
    74  	if fs.Pos == fs.Length {
    75  		if fs.HasFlag {
    76  			fs.AppendString(fs.end)
    77  		}
    78  		return c, true
    79  	} else {
    80  		c = fs.str[fs.Pos]
    81  		if c == fs.flag {
    82  			if fs.Pos < (fs.Length-1) && fs.str[fs.Pos+1] == fs.flag {
    83  				fs.HasFlag = false
    84  				fs.AppendChar(fs.flag)
    85  				fs.Pos += 2
    86  				return fs.Next()
    87  			} else if fs.Pos != fs.Length-1 {
    88  				if fs.HasFlag {
    89  					fs.AppendString(fs.end)
    90  				}
    91  				fs.AppendString(fs.start)
    92  				fs.ChangeFlag = true
    93  				fs.HasFlag = true
    94  			}
    95  		}
    96  	}
    97  	fs.Pos++
    98  	return c, false
    99  }
   100  
   101  var cDateFlagToGo = map[byte]string{
   102  	'a': "mon", 'A': "Monday", 'b': "Jan", 'B': "January", 'c': "02 Jan 06 15:04 MST", 'd': "02",
   103  	'F': "2006-01-02", 'H': "15", 'I': "03", 'm': "01", 'M': "04", 'p': "PM", 'P': "pm", 'S': "05",
   104  	'y': "06", 'Y': "2006", 'z': "-0700", 'Z': "MST"}
   105  
   106  func strftime(t time.Time, cfmt string) string {
   107  	sc := newFlagScanner('%', "", "", cfmt)
   108  	for c, eos := sc.Next(); !eos; c, eos = sc.Next() {
   109  		if !sc.ChangeFlag {
   110  			if sc.HasFlag {
   111  				if v, ok := cDateFlagToGo[c]; ok {
   112  					sc.AppendString(t.Format(v))
   113  				} else {
   114  					switch c {
   115  					case 'w':
   116  						sc.AppendString(fmt.Sprint(int(t.Weekday())))
   117  					default:
   118  						sc.AppendChar('%')
   119  						sc.AppendChar(c)
   120  					}
   121  				}
   122  				sc.HasFlag = false
   123  			} else {
   124  				sc.AppendChar(c)
   125  			}
   126  		}
   127  	}
   128  
   129  	return sc.String()
   130  }
   131  
   132  func isInteger(v LNumber) bool {
   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  }