114 lines
2.2 KiB
Go
114 lines
2.2 KiB
Go
package util
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"unicode"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
func IsNormalString(b []byte) bool {
|
|
str := string(b)
|
|
|
|
// 检查是否为有效的 UTF-8
|
|
if !utf8.ValidString(str) {
|
|
return false
|
|
}
|
|
|
|
// 检查是否全部为可打印字符
|
|
for _, r := range str {
|
|
if !unicode.IsPrint(r) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func MustAnyToInt(v interface{}) int {
|
|
str := fmt.Sprintf("%v", v)
|
|
if i, err := strconv.Atoi(str); err == nil {
|
|
return i
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func IsNumeric(s string) bool {
|
|
for _, r := range s {
|
|
if !unicode.IsDigit(r) {
|
|
return false
|
|
}
|
|
}
|
|
return len(s) > 0
|
|
}
|
|
|
|
func SplitInt64ToTwoInt32(input int64) (int64, int64) {
|
|
return input & 0xFFFFFFFF, input >> 32
|
|
}
|
|
|
|
func Str2List(str string, sep string) []string {
|
|
list := make([]string, 0)
|
|
|
|
if str == "" {
|
|
return list
|
|
}
|
|
|
|
listMap := make(map[string]bool)
|
|
for _, elem := range strings.Split(str, sep) {
|
|
elem = strings.TrimSpace(elem)
|
|
if len(elem) == 0 {
|
|
continue
|
|
}
|
|
if _, ok := listMap[elem]; ok {
|
|
continue
|
|
}
|
|
listMap[elem] = true
|
|
list = append(list, elem)
|
|
}
|
|
|
|
return list
|
|
}
|
|
|
|
// BuildFTSQuery 将用户输入转换为 SQLite FTS5 可以安全解析的查询表达式。
|
|
// - 如果输入包含 AND/OR/NEAR/()/"/* 等高级语法,则直接返回原样,允许高级用户自行控制;
|
|
// - 否则将空白分隔的关键词转换为 "term" AND "term2" 的形式,避免意外的模糊匹配;
|
|
// - 同时会对双引号做转义处理,避免 MATCH 解析失败。
|
|
func BuildFTSQuery(input string) string {
|
|
s := strings.TrimSpace(input)
|
|
if s == "" {
|
|
return ""
|
|
}
|
|
|
|
upper := strings.ToUpper(s)
|
|
advanced := strings.ContainsAny(s, "\"'*()") ||
|
|
strings.Contains(upper, " AND ") ||
|
|
strings.Contains(upper, " OR ") ||
|
|
strings.Contains(upper, " NEAR ") ||
|
|
strings.HasPrefix(upper, "NOT ")
|
|
if advanced {
|
|
return s
|
|
}
|
|
|
|
tokens := strings.Fields(s)
|
|
if len(tokens) == 0 {
|
|
return ""
|
|
}
|
|
|
|
parts := make([]string, 0, len(tokens))
|
|
for _, token := range tokens {
|
|
t := strings.TrimSpace(token)
|
|
if t == "" {
|
|
continue
|
|
}
|
|
t = strings.ReplaceAll(t, "\"", "\"\"")
|
|
parts = append(parts, fmt.Sprintf("\"%s\"", t))
|
|
}
|
|
|
|
if len(parts) == 0 {
|
|
return ""
|
|
}
|
|
|
|
return strings.Join(parts, " AND ")
|
|
}
|