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 //