func strGsub(L *LState) int { str := L.CheckString(1) pat := L.CheckString(2) L.CheckTypes(3, LTString, LTTable, LTFunction) repl := L.CheckAny(3) limit := L.OptInt(4, -1) mds, err := pm.Find(pat, *(*[]byte)(unsafe.Pointer(&str)), 0, limit) if err != nil { L.RaiseError(err.Error()) } if len(mds) == 0 { L.SetTop(1) L.Push(LNumber(0)) return 2 } switch lv := repl.(type) { case LString: L.Push(LString(strGsubStr(L, str, string(lv), mds))) case *LTable: L.Push(LString(strGsubTable(L, str, lv, mds))) case *LFunction: L.Push(LString(strGsubFunc(L, str, lv, mds))) } L.Push(LNumber(len(mds))) return 2 }
func strGmatch(L *LState) int { str := L.CheckString(1) pattern := L.CheckString(2) mds, err := pm.Find(pattern, []byte(str), 0, -1) if err != nil { L.RaiseError(err.Error()) } L.Push(L.Get(UpvalueIndex(1))) ud := L.NewUserData() ud.Value = &strMatchData{str, 0, mds} L.Push(ud) return 2 }
func strFind(L *LState) int { str := L.CheckString(1) pattern := L.CheckString(2) if len(pattern) == 0 { L.Push(LNumber(1)) L.Push(LNumber(0)) return 2 } init := luaIndex2StringIndex(str, L.OptInt(3, 1), true) plain := false if L.GetTop() == 4 { plain = LVAsBool(L.Get(4)) } if len(str) == 0 && len(pattern) == 0 { L.Push(LNumber(1)) return 1 } if plain { pos := strings.Index(str[init:], pattern) if pos < 0 { L.Push(LNil) return 1 } L.Push(LNumber(init+pos) + 1) L.Push(LNumber(init + pos + len(pattern))) return 2 } mds, err := pm.Find(pattern, *(*[]byte)(unsafe.Pointer(&str)), init, 1) if err != nil { L.RaiseError(err.Error()) } if len(mds) == 0 { L.Push(LNil) return 1 } md := mds[0] L.Push(LNumber(md.Capture(0) + 1)) L.Push(LNumber(md.Capture(1))) for i := 2; i < md.CaptureLength(); i += 2 { if md.IsPosCapture(i) { L.Push(LNumber(md.Capture(i))) } else { L.Push(LString(str[md.Capture(i):md.Capture(i+1)])) } } return md.CaptureLength()/2 + 1 }
func strMatch(L *LState) int { str := L.CheckString(1) pattern := L.CheckString(2) offset := L.OptInt(3, 1) l := len(str) if offset < 0 { offset = l + offset + 1 } offset-- if offset < 0 { offset = 0 } mds, err := pm.Find(pattern, *(*[]byte)(unsafe.Pointer(&str)), offset, 1) if err != nil { L.RaiseError(err.Error()) } if len(mds) == 0 { L.Push(LNil) return 0 } md := mds[0] nsubs := md.CaptureLength() / 2 switch nsubs { case 1: L.Push(LString(str[md.Capture(0):md.Capture(1)])) return 1 default: for i := 2; i < md.CaptureLength(); i += 2 { if md.IsPosCapture(i) { L.Push(LNumber(md.Capture(i))) } else { L.Push(LString(str[md.Capture(i):md.Capture(i+1)])) } } return nsubs - 1 } }