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