mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-05 03:23:49 +08:00
refactor(cqcode): drop unsafe for cqcode deserialize
name old time/op new time/op delta CQBot_ConvertStringMessage-8 1.22µs ± 5% 1.14µs ± 4% -6.17% (p=0.000 n=21+18) name old speed new speed delta CQBot_ConvertStringMessage-8 81.2MB/s ± 6% 86.7MB/s ± 3% +6.84% (p=0.000 n=20+18)
This commit is contained in:
parent
111ac7f865
commit
2fbaff8e72
144
coolq/cqcode.go
144
coolq/cqcode.go
@ -14,12 +14,10 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
"github.com/Mrs4s/MiraiGo/message"
|
"github.com/Mrs4s/MiraiGo/message"
|
||||||
@ -49,19 +47,6 @@ var IgnoreInvalidCQCode = false
|
|||||||
// SplitURL 是否分割URL
|
// SplitURL 是否分割URL
|
||||||
var SplitURL = false
|
var SplitURL = false
|
||||||
|
|
||||||
// magicCQ 代表 uint32([]byte("[CQ:"))
|
|
||||||
var magicCQ = uint32(0)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
CQHeader := "[CQ:"
|
|
||||||
magicCQ = *(*uint32)(unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&CQHeader)).Data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// add 指针运算
|
|
||||||
func add(ptr unsafe.Pointer, offset uintptr) unsafe.Pointer {
|
|
||||||
return unsafe.Pointer(uintptr(ptr) + offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
maxImageSize = 1024 * 1024 * 30 // 30MB
|
maxImageSize = 1024 * 1024 * 30 // 30MB
|
||||||
maxVideoSize = 1024 * 1024 * 100 // 100MB
|
maxVideoSize = 1024 * 1024 * 100 // 100MB
|
||||||
@ -397,12 +382,9 @@ func ToStringMessage(e []message.IMessageElement, id int64, isRaw ...bool) (r st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ConvertStringMessage 将消息字符串转为消息元素数组
|
// ConvertStringMessage 将消息字符串转为消息元素数组
|
||||||
func (bot *CQBot) ConvertStringMessage(s string, isGroup bool) (r []message.IMessageElement) {
|
func (bot *CQBot) ConvertStringMessage(raw string, isGroup bool) (r []message.IMessageElement) {
|
||||||
var t, key string
|
var t, key string
|
||||||
d := map[string]string{}
|
d := map[string]string{}
|
||||||
ptr := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data)
|
|
||||||
l := len(s)
|
|
||||||
i, j, CQBegin := 0, 0, 0
|
|
||||||
|
|
||||||
saveCQCode := func() {
|
saveCQCode := func() {
|
||||||
if t == "reply" { // reply 特殊处理
|
if t == "reply" { // reply 特殊处理
|
||||||
@ -487,7 +469,11 @@ func (bot *CQBot) ConvertStringMessage(s string, isGroup bool) (r []message.IMes
|
|||||||
}
|
}
|
||||||
elem, err := bot.ToElement(t, d, isGroup)
|
elem, err := bot.ToElement(t, d, isGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
org := s[CQBegin:i]
|
org := "[CQ:" + t
|
||||||
|
for k, v := range d {
|
||||||
|
org += "," + k + "=" + v
|
||||||
|
}
|
||||||
|
org += "]"
|
||||||
if !IgnoreInvalidCQCode {
|
if !IgnoreInvalidCQCode {
|
||||||
log.Warnf("转换CQ码 %v 时出现错误: %v 将原样发送.", org, err)
|
log.Warnf("转换CQ码 %v 时出现错误: %v 将原样发送.", org, err)
|
||||||
r = append(r, message.NewText(org))
|
r = append(r, message.NewText(org))
|
||||||
@ -504,81 +490,65 @@ func (bot *CQBot) ConvertStringMessage(s string, isGroup bool) (r []message.IMes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
S1: // Plain Text
|
for raw != "" {
|
||||||
for ; i < l; i++ {
|
i := 0
|
||||||
if *(*byte)(add(ptr, uintptr(i))) == '[' && i+4 < l &&
|
for i < len(raw) && !(raw[i] == '[' && i+4 < len(raw) && raw[i:i+4] == "[CQ:") {
|
||||||
*(*uint32)(add(ptr, uintptr(i))) == magicCQ { // Magic :uint32([]byte("[CQ:"))
|
i++
|
||||||
if i > j {
|
}
|
||||||
if SplitURL {
|
if i > 0 {
|
||||||
for _, str := range global.SplitURL(CQCodeUnescapeText(s[j:i])) {
|
if SplitURL {
|
||||||
r = append(r, message.NewText(str))
|
for _, txt := range global.SplitURL(CQCodeUnescapeText(raw[:i])) {
|
||||||
}
|
r = append(r, message.NewText(txt))
|
||||||
} else {
|
|
||||||
r = append(r, message.NewText(CQCodeUnescapeText(s[j:i])))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
r = append(r, message.NewText(CQCodeUnescapeText(raw[:i])))
|
||||||
}
|
}
|
||||||
CQBegin = i
|
|
||||||
i += 4
|
|
||||||
j = i
|
|
||||||
goto S2
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
goto End
|
if i+4 > len(raw) {
|
||||||
S2: // CQCode Type
|
return
|
||||||
for k := range d { // 内存复用,减小GC压力
|
|
||||||
delete(d, k)
|
|
||||||
}
|
|
||||||
for ; i < l; i++ {
|
|
||||||
switch *(*byte)(add(ptr, uintptr(i))) {
|
|
||||||
case ',': // CQ Code with params
|
|
||||||
t = s[j:i]
|
|
||||||
i++
|
|
||||||
j = i
|
|
||||||
goto S3
|
|
||||||
case ']': // CQ Code without params
|
|
||||||
t = s[j:i]
|
|
||||||
i++
|
|
||||||
j = i
|
|
||||||
saveCQCode()
|
|
||||||
goto S1
|
|
||||||
}
|
}
|
||||||
}
|
raw = raw[i+4:] // skip "[CQ:"
|
||||||
goto End
|
i = 0
|
||||||
S3: // CQCode param key
|
for i < len(raw) && raw[i] != ',' && raw[i] != ']' {
|
||||||
for ; i < l; i++ {
|
|
||||||
if *(*byte)(add(ptr, uintptr(i))) == '=' {
|
|
||||||
key = s[j:i]
|
|
||||||
i++
|
i++
|
||||||
j = i
|
|
||||||
goto S4
|
|
||||||
}
|
}
|
||||||
}
|
if i+1 > len(raw) {
|
||||||
goto End
|
return
|
||||||
S4: // CQCode param value
|
|
||||||
for ; i < l; i++ {
|
|
||||||
switch *(*byte)(add(ptr, uintptr(i))) {
|
|
||||||
case ',': // more param
|
|
||||||
d[key] = CQCodeUnescapeValue(s[j:i])
|
|
||||||
i++
|
|
||||||
j = i
|
|
||||||
goto S3
|
|
||||||
case ']':
|
|
||||||
d[key] = CQCodeUnescapeValue(s[j:i])
|
|
||||||
i++
|
|
||||||
j = i
|
|
||||||
saveCQCode()
|
|
||||||
goto S1
|
|
||||||
}
|
}
|
||||||
}
|
t = raw[:i]
|
||||||
goto End
|
for k := range d { // clear the map, reuse it
|
||||||
End:
|
delete(d, k)
|
||||||
if i > j {
|
}
|
||||||
if SplitURL {
|
raw = raw[i:]
|
||||||
for _, str := range global.SplitURL(CQCodeUnescapeText(s[j:i])) {
|
i = 0
|
||||||
r = append(r, message.NewText(str))
|
for {
|
||||||
|
if raw[0] == ']' {
|
||||||
|
saveCQCode()
|
||||||
|
raw = raw[1:]
|
||||||
|
break
|
||||||
}
|
}
|
||||||
} else {
|
raw = raw[1:]
|
||||||
r = append(r, message.NewText(CQCodeUnescapeText(s[j:i])))
|
|
||||||
|
for i < len(raw) && raw[i] != '=' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i+1 > len(raw) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
key = raw[:i]
|
||||||
|
raw = raw[i+1:] // skip "="
|
||||||
|
i = 0
|
||||||
|
for i < len(raw) && raw[i] != ',' && raw[i] != ']' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if i+1 > len(raw) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d[key] = CQCodeUnescapeValue(raw[:i])
|
||||||
|
raw = raw[i:]
|
||||||
|
i = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -22,6 +22,7 @@ func BenchmarkCQBot_ConvertStringMessage(b *testing.B) {
|
|||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
bot.ConvertStringMessage(bench, false)
|
bot.ConvertStringMessage(bench, false)
|
||||||
}
|
}
|
||||||
|
b.SetBytes(int64(len(bench)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkCQBot_ConvertObjectMessage(b *testing.B) {
|
func BenchmarkCQBot_ConvertObjectMessage(b *testing.B) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user