github.com/yuin/gopher-lua@v1.1.2-0.20231212122839-2348fd042596/auxlib.go (about)

     1  package lua
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"strings"
     9  )
    10  
    11  /* checkType {{{ */
    12  
    13  func (ls *LState) CheckAny(n int) LValue {
    14  	if n > ls.GetTop() {
    15  		ls.ArgError(n, "value expected")
    16  	}
    17  	return ls.Get(n)
    18  }
    19  
    20  func (ls *LState) CheckInt(n int) int {
    21  	v := ls.Get(n)
    22  	if intv, ok := v.(LNumber); ok {
    23  		return int(intv)
    24  	}
    25  	ls.TypeError(n, LTNumber)
    26  	return 0
    27  }
    28  
    29  func (ls *LState) CheckInt64(n int) int64 {
    30  	v := ls.Get(n)
    31  	if intv, ok := v.(LNumber); ok {
    32  		return int64(intv)
    33  	}
    34  	ls.TypeError(n, LTNumber)
    35  	return 0
    36  }
    37  
    38  func (ls *LState) CheckNumber(n int) LNumber {
    39  	v := ls.Get(n)
    40  	if lv, ok := v.(LNumber); ok {
    41  		return lv
    42  	}
    43  	if lv, ok := v.(LString); ok {
    44  		if num, err := parseNumber(string(lv)); err == nil {
    45  			return num
    46  		}
    47  	}
    48  	ls.TypeError(n, LTNumber)
    49  	return 0
    50  }
    51  
    52  func (ls *LState) CheckString(n int) string {
    53  	v := ls.Get(n)
    54  	if lv, ok := v.(LString); ok {
    55  		return string(lv)
    56  	} else if LVCanConvToString(v) {
    57  		return ls.ToString(n)
    58  	}
    59  	ls.TypeError(n, LTString)
    60  	return ""
    61  }
    62  
    63  func (ls *LState) CheckBool(n int) bool {
    64  	v := ls.Get(n)
    65  	if lv, ok := v.(LBool); ok {
    66  		return bool(lv)
    67  	}
    68  	ls.TypeError(n, LTBool)
    69  	return false
    70  }
    71  
    72  func (ls *LState) CheckTable(n int) *LTable {
    73  	v := ls.Get(n)
    74  	if lv, ok := v.(*LTable); ok {
    75  		return lv
    76  	}
    77  	ls.TypeError(n, LTTable)
    78  	return nil
    79  }
    80  
    81  func (ls *LState) CheckFunction(n int) *LFunction {
    82  	v := ls.Get(n)
    83  	if lv, ok := v.(*LFunction); ok {
    84  		return lv
    85  	}
    86  	ls.TypeError(n, LTFunction)
    87  	return nil
    88  }
    89  
    90  func (ls *LState) CheckUserData(n int) *LUserData {
    91  	v := ls.Get(n)
    92  	if lv, ok := v.(*LUserData); ok {
    93  		return lv
    94  	}
    95  	ls.TypeError(n, LTUserData)
    96  	return nil
    97  }
    98  
    99  func (ls *LState) CheckThread(n int) *LState {
   100  	v := ls.Get(n)
   101  	if lv, ok := v.(*LState); ok {
   102  		return lv
   103  	}
   104  	ls.TypeError(n, LTThread)
   105  	return nil
   106  }
   107  
   108  func (ls *LState) CheckType(n int, typ LValueType) {
   109  	v := ls.Get(n)
   110  	if v.Type() != typ {
   111  		ls.TypeError(n, typ)
   112  	}
   113  }
   114  
   115  func (ls *LState) CheckTypes(n int, typs ...LValueType) {
   116  	vt := ls.Get(n).Type()
   117  	for _, typ := range typs {
   118  		if vt == typ {
   119  			return
   120  		}
   121  	}
   122  	buf := []string{}
   123  	for _, typ := range typs {
   124  		buf = append(buf, typ.String())
   125  	}
   126  	ls.ArgError(n, strings.Join(buf, " or ")+" expected, got "+ls.Get(n).Type().String())
   127  }
   128  
   129  func (ls *LState) CheckOption(n int, options []string) int {
   130  	str := ls.CheckString(n)
   131  	for i, v := range options {
   132  		if v == str {
   133  			return i
   134  		}
   135  	}
   136  	ls.ArgError(n, fmt.Sprintf("invalid option: %s (must be one of %s)", str, strings.Join(options, ",")))
   137  	return 0
   138  }
   139  
   140  /* }}} */
   141  
   142  /* optType {{{ */
   143  
   144  func (ls *LState) OptInt(n int, d int) int {
   145  	v := ls.Get(n)
   146  	if v == LNil {
   147  		return d
   148  	}
   149  	if intv, ok := v.(LNumber); ok {
   150  		return int(intv)
   151  	}
   152  	ls.TypeError(n, LTNumber)
   153  	return 0
   154  }
   155  
   156  func (ls *LState) OptInt64(n int, d int64) int64 {
   157  	v := ls.Get(n)
   158  	if v == LNil {
   159  		return d
   160  	}
   161  	if intv, ok := v.(LNumber); ok {
   162  		return int64(intv)
   163  	}
   164  	ls.TypeError(n, LTNumber)
   165  	return 0
   166  }
   167  
   168  func (ls *LState) OptNumber(n int, d LNumber) LNumber {
   169  	v := ls.Get(n)
   170  	if v == LNil {
   171  		return d
   172  	}
   173  	if lv, ok := v.(LNumber); ok {
   174  		return lv
   175  	}
   176  	ls.TypeError(n, LTNumber)
   177  	return 0
   178  }
   179  
   180  func (ls *LState) OptString(n int, d string) string {
   181  	v := ls.Get(n)
   182  	if v == LNil {
   183  		return d
   184  	}
   185  	if lv, ok := v.(LString); ok {
   186  		return string(lv)
   187  	}
   188  	ls.TypeError(n, LTString)
   189  	return ""
   190  }
   191  
   192  func (ls *LState) OptBool(n int, d bool) bool {
   193  	v := ls.Get(n)
   194  	if v == LNil {
   195  		return d
   196  	}
   197  	if lv, ok := v.(LBool); ok {
   198  		return bool(lv)
   199  	}
   200  	ls.TypeError(n, LTBool)
   201  	return false
   202  }
   203  
   204  func (ls *LState) OptTable(n int, d *LTable) *LTable {
   205  	v := ls.Get(n)
   206  	if v == LNil {
   207  		return d
   208  	}
   209  	if lv, ok := v.(*LTable); ok {
   210  		return lv
   211  	}
   212  	ls.TypeError(n, LTTable)
   213  	return nil
   214  }
   215  
   216  func (ls *LState) OptFunction(n int, d *LFunction) *LFunction {
   217  	v := ls.Get(n)
   218  	if v == LNil {
   219  		return d
   220  	}
   221  	if lv, ok := v.(*LFunction); ok {
   222  		return lv
   223  	}
   224  	ls.TypeError(n, LTFunction)
   225  	return nil
   226  }
   227  
   228  func (ls *LState) OptUserData(n int, d *LUserData) *LUserData {
   229  	v := ls.Get(n)
   230  	if v == LNil {
   231  		return d
   232  	}
   233  	if lv, ok := v.(*LUserData); ok {
   234  		return lv
   235  	}
   236  	ls.TypeError(n, LTUserData)
   237  	return nil
   238  }
   239  
   240  /* }}} */
   241  
   242  /* error operations {{{ */
   243  
   244  func (ls *LState) ArgError(n int, message string) {
   245  	ls.RaiseError("bad argument #%v to %v (%v)", n, ls.rawFrameFuncName(ls.currentFrame), message)
   246  }
   247  
   248  func (ls *LState) TypeError(n int, typ LValueType) {
   249  	ls.RaiseError("bad argument #%v to %v (%v expected, got %v)", n, ls.rawFrameFuncName(ls.currentFrame), typ.String(), ls.Get(n).Type().String())
   250  }
   251  
   252  /* }}} */
   253  
   254  /* debug operations {{{ */
   255  
   256  func (ls *LState) Where(level int) string {
   257  	return ls.where(level, false)
   258  }
   259  
   260  /* }}} */
   261  
   262  /* table operations {{{ */
   263  
   264  func (ls *LState) FindTable(obj *LTable, n string, size int) LValue {
   265  	names := strings.Split(n, ".")
   266  	curobj := obj
   267  	for _, name := range names {
   268  		if curobj.Type() != LTTable {
   269  			return LNil
   270  		}
   271  		nextobj := ls.RawGet(curobj, LString(name))
   272  		if nextobj == LNil {
   273  			tb := ls.CreateTable(0, size)
   274  			ls.RawSet(curobj, LString(name), tb)
   275  			curobj = tb
   276  		} else if nextobj.Type() != LTTable {
   277  			return LNil
   278  		} else {
   279  			curobj = nextobj.(*LTable)
   280  		}
   281  	}
   282  	return curobj
   283  }
   284  
   285  /* }}} */
   286  
   287  /* register operations {{{ */
   288  
   289  func (ls *LState) RegisterModule(name string, funcs map[string]LGFunction) LValue {
   290  	tb := ls.FindTable(ls.Get(RegistryIndex).(*LTable), "_LOADED", 1)
   291  	mod := ls.GetField(tb, name)
   292  	if mod.Type() != LTTable {
   293  		newmod := ls.FindTable(ls.Get(GlobalsIndex).(*LTable), name, len(funcs))
   294  		if newmodtb, ok := newmod.(*LTable); !ok {
   295  			ls.RaiseError("name conflict for module(%v)", name)
   296  		} else {
   297  			for fname, fn := range funcs {
   298  				newmodtb.RawSetString(fname, ls.NewFunction(fn))
   299  			}
   300  			ls.SetField(tb, name, newmodtb)
   301  			return newmodtb
   302  		}
   303  	}
   304  	return mod
   305  }
   306  
   307  func (ls *LState) SetFuncs(tb *LTable, funcs map[string]LGFunction, upvalues ...LValue) *LTable {
   308  	for fname, fn := range funcs {
   309  		tb.RawSetString(fname, ls.NewClosure(fn, upvalues...))
   310  	}
   311  	return tb
   312  }
   313  
   314  /* }}} */
   315  
   316  /* metatable operations {{{ */
   317  
   318  func (ls *LState) NewTypeMetatable(typ string) *LTable {
   319  	regtable := ls.Get(RegistryIndex)
   320  	mt := ls.GetField(regtable, typ)
   321  	if tb, ok := mt.(*LTable); ok {
   322  		return tb
   323  	}
   324  	mtnew := ls.NewTable()
   325  	ls.SetField(regtable, typ, mtnew)
   326  	return mtnew
   327  }
   328  
   329  func (ls *LState) GetMetaField(obj LValue, event string) LValue {
   330  	return ls.metaOp1(obj, event)
   331  }
   332  
   333  func (ls *LState) GetTypeMetatable(typ string) LValue {
   334  	return ls.GetField(ls.Get(RegistryIndex), typ)
   335  }
   336  
   337  func (ls *LState) CallMeta(obj LValue, event string) LValue {
   338  	op := ls.metaOp1(obj, event)
   339  	if op.Type() == LTFunction {
   340  		ls.reg.Push(op)
   341  		ls.reg.Push(obj)
   342  		ls.Call(1, 1)
   343  		return ls.reg.Pop()
   344  	}
   345  	return LNil
   346  }
   347  
   348  /* }}} */
   349  
   350  /* load and function call operations {{{ */
   351  
   352  func (ls *LState) LoadFile(path string) (*LFunction, error) {
   353  	var file *os.File
   354  	var err error
   355  	if len(path) == 0 {
   356  		file = os.Stdin
   357  	} else {
   358  		file, err = os.Open(path)
   359  		defer file.Close()
   360  		if err != nil {
   361  			return nil, newApiErrorE(ApiErrorFile, err)
   362  		}
   363  	}
   364  
   365  	reader := bufio.NewReader(file)
   366  	// get the first character.
   367  	c, err := reader.ReadByte()
   368  	if err != nil && err != io.EOF {
   369  		return nil, newApiErrorE(ApiErrorFile, err)
   370  	}
   371  	if c == byte('#') {
   372  		// Unix exec. file?
   373  		// skip first line
   374  		_, err, _ = readBufioLine(reader)
   375  		if err != nil {
   376  			return nil, newApiErrorE(ApiErrorFile, err)
   377  		}
   378  	}
   379  
   380  	if err != io.EOF {
   381  		// if the file is not empty,
   382  		// unread the first character of the file or newline character(readBufioLine's last byte).
   383  		err = reader.UnreadByte()
   384  		if err != nil {
   385  			return nil, newApiErrorE(ApiErrorFile, err)
   386  		}
   387  	}
   388  
   389  	return ls.Load(reader, path)
   390  }
   391  
   392  func (ls *LState) LoadString(source string) (*LFunction, error) {
   393  	return ls.Load(strings.NewReader(source), "<string>")
   394  }
   395  
   396  func (ls *LState) DoFile(path string) error {
   397  	if fn, err := ls.LoadFile(path); err != nil {
   398  		return err
   399  	} else {
   400  		ls.Push(fn)
   401  		return ls.PCall(0, MultRet, nil)
   402  	}
   403  }
   404  
   405  func (ls *LState) DoString(source string) error {
   406  	if fn, err := ls.LoadString(source); err != nil {
   407  		return err
   408  	} else {
   409  		ls.Push(fn)
   410  		return ls.PCall(0, MultRet, nil)
   411  	}
   412  }
   413  
   414  /* }}} */
   415  
   416  /* GopherLua original APIs {{{ */
   417  
   418  // ToStringMeta returns string representation of given LValue.
   419  // This method calls the `__tostring` meta method if defined.
   420  func (ls *LState) ToStringMeta(lv LValue) LValue {
   421  	if fn, ok := ls.metaOp1(lv, "__tostring").(*LFunction); ok {
   422  		ls.Push(fn)
   423  		ls.Push(lv)
   424  		ls.Call(1, 1)
   425  		return ls.reg.Pop()
   426  	} else {
   427  		return LString(lv.String())
   428  	}
   429  }
   430  
   431  // Set a module loader to the package.preload table.
   432  func (ls *LState) PreloadModule(name string, loader LGFunction) {
   433  	preload := ls.GetField(ls.GetField(ls.Get(EnvironIndex), "package"), "preload")
   434  	if _, ok := preload.(*LTable); !ok {
   435  		ls.RaiseError("package.preload must be a table")
   436  	}
   437  	ls.SetField(preload, name, ls.NewFunction(loader))
   438  }
   439  
   440  // Checks whether the given index is an LChannel and returns this channel.
   441  func (ls *LState) CheckChannel(n int) chan LValue {
   442  	v := ls.Get(n)
   443  	if ch, ok := v.(LChannel); ok {
   444  		return (chan LValue)(ch)
   445  	}
   446  	ls.TypeError(n, LTChannel)
   447  	return nil
   448  }
   449  
   450  // If the given index is a LChannel, returns this channel. If this argument is absent or is nil, returns ch. Otherwise, raises an error.
   451  func (ls *LState) OptChannel(n int, ch chan LValue) chan LValue {
   452  	v := ls.Get(n)
   453  	if v == LNil {
   454  		return ch
   455  	}
   456  	if ch, ok := v.(LChannel); ok {
   457  		return (chan LValue)(ch)
   458  	}
   459  	ls.TypeError(n, LTChannel)
   460  	return nil
   461  }
   462  
   463  /* }}} */
   464  
   465  //