Trie 优化 设置的前缀, 改了构建的方式
This commit is contained in:
parent
c28147be31
commit
420f307ad2
4
base.go
4
base.go
@ -12,7 +12,7 @@ type parseFunction struct {
|
|||||||
ExecuteFunction func(u *CURL, soption string)
|
ExecuteFunction func(u *CURL, soption string)
|
||||||
ParamCURL *CURL
|
ParamCURL *CURL
|
||||||
ParamData string
|
ParamData string
|
||||||
Prioty int
|
Priority int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute 执行 函数
|
// Execute 执行 函数
|
||||||
@ -29,7 +29,7 @@ func (nodes *parseQueue) Swap(i, j int) {
|
|||||||
// Less Priority Want Less
|
// Less Priority Want Less
|
||||||
func (nodes *parseQueue) Less(i, j int) bool {
|
func (nodes *parseQueue) Less(i, j int) bool {
|
||||||
ns := *nodes
|
ns := *nodes
|
||||||
return ns[i].Prioty < ns[j].Prioty
|
return ns[i].Priority < ns[j].Priority
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push 实现heap.Interface接口定义的额外方法
|
// Push 实现heap.Interface接口定义的额外方法
|
||||||
|
16
base_test.go
16
base_test.go
@ -7,17 +7,17 @@ import (
|
|||||||
|
|
||||||
func TestPQueue(t *testing.T) {
|
func TestPQueue(t *testing.T) {
|
||||||
PQExec := newPQueueExecute()
|
PQExec := newPQueueExecute()
|
||||||
PQExec.Push(&parseFunction{Prioty: 5})
|
PQExec.Push(&parseFunction{Priority: 5})
|
||||||
PQExec.Push(&parseFunction{Prioty: 10})
|
PQExec.Push(&parseFunction{Priority: 10})
|
||||||
PQExec.Push(&parseFunction{Prioty: 4})
|
PQExec.Push(&parseFunction{Priority: 4})
|
||||||
PQExec.Push(&parseFunction{Prioty: 4})
|
PQExec.Push(&parseFunction{Priority: 4})
|
||||||
PQExec.Push(&parseFunction{Prioty: 20})
|
PQExec.Push(&parseFunction{Priority: 20})
|
||||||
PQExec.Push(&parseFunction{Prioty: 10})
|
PQExec.Push(&parseFunction{Priority: 10})
|
||||||
PQExec.Push(&parseFunction{Prioty: 15})
|
PQExec.Push(&parseFunction{Priority: 15})
|
||||||
|
|
||||||
content := ""
|
content := ""
|
||||||
for PQExec.Len() > 0 {
|
for PQExec.Len() > 0 {
|
||||||
content += strconv.Itoa(PQExec.Pop().Prioty)
|
content += strconv.Itoa(PQExec.Pop().Priority)
|
||||||
content += " "
|
content += " "
|
||||||
}
|
}
|
||||||
if content != "4 4 5 10 10 15 20 " {
|
if content != "4 4 5 10 10 15 20 " {
|
||||||
|
67
option.go
Normal file
67
option.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package curl2info
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
optionTrie = NewTrie()
|
||||||
|
oelist := []*optionExecute{
|
||||||
|
{"-H", 10, parseHeader, nil},
|
||||||
|
{"-X", 10, parseOptX, nil},
|
||||||
|
{"-A", 15, parseUserAgent, &extract{re: "^-A +(.+)", execute: extractData}},
|
||||||
|
{"-I", 15, parseOptI, nil},
|
||||||
|
{"-d", 10, parseBodyASCII, &extract{re: "^-d +(.+)", execute: extractData}},
|
||||||
|
{"-u", 15, parseUser, &extract{re: "^-u +(.+)", execute: extractData}},
|
||||||
|
{"-k", 15, parseInsecure, nil},
|
||||||
|
// Body
|
||||||
|
{"--data", 10, parseBodyASCII, &extract{re: "--data +(.+)", execute: extractData}},
|
||||||
|
{"--data-urlencode", 10, parseBodyURLEncode, &extract{re: "--data-urlencode +(.+)", execute: extractData}},
|
||||||
|
{"--data-binary", 10, parseBodyBinary, &extract{re: "--data-binary +(.+)", execute: extractData}},
|
||||||
|
{"--data-ascii", 10, parseBodyASCII, &extract{re: "--data-ascii +(.+)", execute: extractData}},
|
||||||
|
{"--data-raw", 10, parseBodyRaw, &extract{re: "--data-raw +(.+)", execute: extractData}},
|
||||||
|
//"--"
|
||||||
|
{"--header", 10, parseHeader, nil},
|
||||||
|
{"--insecure", 15, parseInsecure, nil},
|
||||||
|
{"--call", 10, parseCallBack, &extract{re: "--call +(.+)", execute: extractData}},
|
||||||
|
{"--user-agent", 15, parseUserAgent, &extract{re: "--user-agent +(.+)", execute: extractData}},
|
||||||
|
{"--user", 15, parseUser, &extract{re: "--user +(.+)", execute: extractData}},
|
||||||
|
{"--connect-timeout", 15, parseTimeout, &extract{re: "--connect-timeout +(.+)", execute: extractData}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, oe := range oelist {
|
||||||
|
optionTrie.Insert(oe)
|
||||||
|
}
|
||||||
|
|
||||||
|
// log.Println("support options:", optionTrie.AllWords())
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract 用于提取设置的数据
|
||||||
|
type extract struct {
|
||||||
|
re string
|
||||||
|
execute func(re, soption string) string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (et *extract) Execute(soption string) string {
|
||||||
|
return et.execute(et.re, soption)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptionTrie 设置的前缀树
|
||||||
|
var optionTrie *Trie
|
||||||
|
|
||||||
|
type optionExecute struct {
|
||||||
|
Prefix string
|
||||||
|
|
||||||
|
Priority int
|
||||||
|
|
||||||
|
Execute func(*CURL, string) // 执行函数
|
||||||
|
Extract *extract // 提取的方法结构与参数
|
||||||
|
}
|
||||||
|
|
||||||
|
func (oe *optionExecute) GetWord() string {
|
||||||
|
return oe.Prefix + " "
|
||||||
|
}
|
||||||
|
|
||||||
|
func (oe *optionExecute) BuildFunction(curl *CURL, soption string) *parseFunction {
|
||||||
|
data := soption
|
||||||
|
if oe.Extract != nil {
|
||||||
|
data = oe.Extract.Execute(data)
|
||||||
|
}
|
||||||
|
return &parseFunction{ParamCURL: curl, ParamData: data, ExecuteFunction: oe.Execute, Priority: oe.Priority}
|
||||||
|
}
|
110
parse_curl.go
110
parse_curl.go
@ -99,7 +99,39 @@ func (curl *CURL) CreateWorkflow(ses *requests.Session) *requests.Workflow {
|
|||||||
return wf
|
return wf
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseRawCURL curl_bash
|
func init() {
|
||||||
|
optionTrie = NewTrie()
|
||||||
|
oelist := []*optionExecute{
|
||||||
|
{"-H", 10, parseHeader, nil},
|
||||||
|
{"-X", 10, parseOptX, nil},
|
||||||
|
{"-A", 15, parseUserAgent, &extract{re: "^-A +(.+)", execute: extractData}},
|
||||||
|
{"-I", 15, parseOptI, nil},
|
||||||
|
{"-d", 10, parseBodyASCII, &extract{re: "^-d +(.+)", execute: extractData}},
|
||||||
|
{"-u", 15, parseUser, &extract{re: "^-u +(.+)", execute: extractData}},
|
||||||
|
{"-k", 15, parseInsecure, nil},
|
||||||
|
// Body
|
||||||
|
{"--data", 10, parseBodyASCII, &extract{re: "--data +(.+)", execute: extractData}},
|
||||||
|
{"--data-urlencode", 10, parseBodyURLEncode, &extract{re: "--data-urlencode +(.+)", execute: extractData}},
|
||||||
|
{"--data-binary", 10, parseBodyBinary, &extract{re: "--data-binary +(.+)", execute: extractData}},
|
||||||
|
{"--data-ascii", 10, parseBodyASCII, &extract{re: "--data-ascii +(.+)", execute: extractData}},
|
||||||
|
{"--data-raw", 10, parseBodyRaw, &extract{re: "--data-raw +(.+)", execute: extractData}},
|
||||||
|
//"--"
|
||||||
|
{"--header", 10, parseHeader, nil},
|
||||||
|
{"--insecure", 15, parseInsecure, nil},
|
||||||
|
{"--call", 10, parseCallBack, &extract{re: "--call +(.+)", execute: extractData}},
|
||||||
|
{"--user-agent", 15, parseUserAgent, &extract{re: "--user-agent +(.+)", execute: extractData}},
|
||||||
|
{"--user", 15, parseUser, &extract{re: "--user +(.+)", execute: extractData}},
|
||||||
|
{"--connect-timeout", 15, parseTimeout, &extract{re: "--connect-timeout +(.+)", execute: extractData}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, oe := range oelist {
|
||||||
|
optionTrie.Insert(oe)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("support options:", optionTrie.AllWords())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseRawCURL curl_bash 可以用trie改进 没空改
|
||||||
func ParseRawCURL(scurl string) (cURL *CURL, err error) {
|
func ParseRawCURL(scurl string) (cURL *CURL, err error) {
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -110,20 +142,17 @@ func ParseRawCURL(scurl string) (cURL *CURL, err error) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
executor := newPQueueExecute()
|
executor := newPQueueExecute()
|
||||||
|
|
||||||
curl := NewCURL()
|
curl := NewCURL()
|
||||||
|
|
||||||
if scurl[0] == '"' && scurl[len(scurl)-1] == '"' {
|
if scurl[0] == '"' && scurl[len(scurl)-1] == '"' {
|
||||||
scurl = strings.Trim(scurl, `"`)
|
scurl = strings.Trim(scurl, `"`)
|
||||||
scurl = strings.TrimSpace(scurl)
|
|
||||||
} else if scurl[0] == '\'' && scurl[len(scurl)-1] == '\'' {
|
} else if scurl[0] == '\'' && scurl[len(scurl)-1] == '\'' {
|
||||||
scurl = strings.Trim(scurl, `'`)
|
scurl = strings.Trim(scurl, `'`)
|
||||||
scurl = strings.TrimSpace(scurl)
|
|
||||||
} else {
|
|
||||||
scurl = strings.TrimSpace(scurl)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scurl = strings.TrimSpace(scurl)
|
||||||
scurl = strings.TrimLeft(scurl, "curl")
|
scurl = strings.TrimLeft(scurl, "curl")
|
||||||
|
|
||||||
mathches := regexp.MustCompile(`--[^ ]+ +'[^']+'|--[^ ]+ +[^ ]+|-[A-Za-z] +'[^']+'|-[A-Za-z] +[^ ]+| '[^']+'|--[a-z]+ {0,}`).FindAllString(scurl, -1)
|
mathches := regexp.MustCompile(`--[^ ]+ +'[^']+'|--[^ ]+ +[^ ]+|-[A-Za-z] +'[^']+'|-[A-Za-z] +[^ ]+| '[^']+'|--[a-z]+ {0,}`).FindAllString(scurl, -1)
|
||||||
for _, m := range mathches {
|
for _, m := range mathches {
|
||||||
m = strings.TrimSpace(m)
|
m = strings.TrimSpace(m)
|
||||||
@ -135,7 +164,7 @@ func ParseRawCURL(scurl string) (cURL *CURL, err error) {
|
|||||||
}
|
}
|
||||||
curl.ParsedURL = purl
|
curl.ParsedURL = purl
|
||||||
case '-':
|
case '-':
|
||||||
exec := judgeAndParseOptions(curl, m)
|
exec := judgeOptions(curl, m)
|
||||||
if exec != nil {
|
if exec != nil {
|
||||||
executor.Push(exec)
|
executor.Push(exec)
|
||||||
}
|
}
|
||||||
@ -154,27 +183,38 @@ func ParseRawCURL(scurl string) (cURL *CURL, err error) {
|
|||||||
return curl, nil
|
return curl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func judgeOptions(u *CURL, soption string) *parseFunction {
|
||||||
|
word := TrieStrWord(soption)
|
||||||
|
if ioe := optionTrie.SearchMostPrefix(&word); ioe != nil {
|
||||||
|
oe := ioe.(*optionExecute)
|
||||||
|
return oe.BuildFunction(u, soption)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println(soption, " no haved this option")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func judgeAndParseOptions(u *CURL, soption string) *parseFunction {
|
func judgeAndParseOptions(u *CURL, soption string) *parseFunction {
|
||||||
switch prefix := soption[0:2]; prefix {
|
switch prefix := soption[0:2]; prefix {
|
||||||
case "-H":
|
case "-H":
|
||||||
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseHeader, Prioty: 10}
|
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseHeader, Priority: 10}
|
||||||
case "-X":
|
case "-X":
|
||||||
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseOptX, Prioty: 10}
|
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseOptX, Priority: 10}
|
||||||
case "-A": // User-Agent 先后顺序的问题
|
case "-A": // User-Agent 先后顺序的问题
|
||||||
data := extractData("^-A +(.+)", soption)
|
data := extractData("^-A +(.+)", soption)
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseUserAgent, Prioty: 15}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseUserAgent, Priority: 15}
|
||||||
case "-I":
|
case "-I":
|
||||||
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseOptI, Prioty: 15}
|
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseOptI, Priority: 15}
|
||||||
case "--":
|
case "--":
|
||||||
return parseLongOption(u, soption)
|
return parseLongOption(u, soption)
|
||||||
case "-d":
|
case "-d":
|
||||||
data := extractData("^-d +(.+)", soption)
|
data := extractData("^-d +(.+)", soption)
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyASCII, Prioty: 10}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyASCII, Priority: 10}
|
||||||
case "-u":
|
case "-u":
|
||||||
data := extractData("^-u +(.+)", soption)
|
data := extractData("^-u +(.+)", soption)
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseUser, Prioty: 15}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseUser, Priority: 15}
|
||||||
case "-k": // -k, --insecure Allow insecure server connections when using SSL
|
case "-k": // -k, --insecure Allow insecure server connections when using SSL
|
||||||
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseInsecure, Prioty: 15}
|
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseInsecure, Priority: 15}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -193,39 +233,35 @@ func parseLongOption(u *CURL, soption string) *parseFunction {
|
|||||||
dtype := datas[1]
|
dtype := datas[1]
|
||||||
data := strings.Trim(datas[2], "'")
|
data := strings.Trim(datas[2], "'")
|
||||||
|
|
||||||
if u.Method != "" {
|
|
||||||
u.Method = "POST"
|
|
||||||
}
|
|
||||||
|
|
||||||
switch dtype {
|
switch dtype {
|
||||||
case "binary":
|
case "binary":
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyBinary, Prioty: 10}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyBinary, Priority: 10}
|
||||||
case "ascii":
|
case "ascii":
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyASCII, Prioty: 10}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyASCII, Priority: 10}
|
||||||
case "raw":
|
case "raw":
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyRaw, Prioty: 10}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyRaw, Priority: 10}
|
||||||
case "urlencode":
|
case "urlencode":
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyURLEncode, Prioty: 10}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyURLEncode, Priority: 10}
|
||||||
case "data":
|
case "data":
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyASCII, Prioty: 10}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyASCII, Priority: 10}
|
||||||
}
|
}
|
||||||
|
|
||||||
case regexp.MustCompile("^--header").MatchString(soption):
|
case regexp.MustCompile("^--header").MatchString(soption):
|
||||||
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseHeader, Prioty: 10}
|
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseHeader, Priority: 10}
|
||||||
case regexp.MustCompile("^--call").MatchString(soption):
|
case regexp.MustCompile("^--call").MatchString(soption):
|
||||||
data := extractData("^--call +(.+)", soption)
|
data := extractData("^--call +(.+)", soption)
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseCallBack, Prioty: 10}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseCallBack, Priority: 10}
|
||||||
case regexp.MustCompile("^--user-agent").MatchString(soption):
|
case regexp.MustCompile("^--user-agent").MatchString(soption):
|
||||||
data := extractData("^--user-agent +(.+)", soption)
|
data := extractData("^--user-agent +(.+)", soption)
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseUserAgent, Prioty: 15}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseUserAgent, Priority: 15}
|
||||||
case regexp.MustCompile("^--user").MatchString(soption):
|
case regexp.MustCompile("^--user").MatchString(soption):
|
||||||
data := extractData("^--user +(.+)", soption)
|
data := extractData("^--user +(.+)", soption)
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseUser, Prioty: 15}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseUser, Priority: 15}
|
||||||
case regexp.MustCompile("^--insecure").MatchString(soption):
|
case regexp.MustCompile("^--insecure").MatchString(soption):
|
||||||
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseInsecure, Prioty: 15}
|
return &parseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseInsecure, Priority: 15}
|
||||||
case regexp.MustCompile("^--connect-timeout").MatchString(soption):
|
case regexp.MustCompile("^--connect-timeout").MatchString(soption):
|
||||||
data := extractData("^--connect-timeout +(.+)", soption)
|
data := extractData("^--connect-timeout +(.+)", soption)
|
||||||
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseTimeout, Prioty: 15}
|
return &parseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseTimeout, Priority: 15}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("can't parseOption", soption)
|
log.Println("can't parseOption", soption)
|
||||||
@ -273,16 +309,28 @@ func parseOptX(u *CURL, soption string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseBodyURLEncode(u *CURL, data string) {
|
func parseBodyURLEncode(u *CURL, data string) {
|
||||||
|
if u.Method != "" {
|
||||||
|
u.Method = "POST"
|
||||||
|
}
|
||||||
|
|
||||||
u.Body.SetPrefix(requests.TypeURLENCODED)
|
u.Body.SetPrefix(requests.TypeURLENCODED)
|
||||||
u.Body.SetIOBody(data)
|
u.Body.SetIOBody(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBodyRaw(u *CURL, data string) {
|
func parseBodyRaw(u *CURL, data string) {
|
||||||
|
if u.Method != "" {
|
||||||
|
u.Method = "POST"
|
||||||
|
}
|
||||||
|
|
||||||
u.Body.SetPrefix(requests.TypeURLENCODED)
|
u.Body.SetPrefix(requests.TypeURLENCODED)
|
||||||
u.Body.SetIOBody(data)
|
u.Body.SetIOBody(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBodyASCII(u *CURL, data string) {
|
func parseBodyASCII(u *CURL, data string) {
|
||||||
|
if u.Method != "" {
|
||||||
|
u.Method = "POST"
|
||||||
|
}
|
||||||
|
|
||||||
u.Body.SetPrefix(requests.TypeURLENCODED)
|
u.Body.SetPrefix(requests.TypeURLENCODED)
|
||||||
|
|
||||||
if data[0] != '@' {
|
if data[0] != '@' {
|
||||||
@ -304,6 +352,10 @@ func parseBodyASCII(u *CURL, data string) {
|
|||||||
|
|
||||||
// 处理@ 并且替/r/n符号
|
// 处理@ 并且替/r/n符号
|
||||||
func parseBodyBinary(u *CURL, data string) {
|
func parseBodyBinary(u *CURL, data string) {
|
||||||
|
if u.Method != "" {
|
||||||
|
u.Method = "POST"
|
||||||
|
}
|
||||||
|
|
||||||
u.Body.SetPrefix(requests.TypeURLENCODED)
|
u.Body.SetPrefix(requests.TypeURLENCODED)
|
||||||
|
|
||||||
if data[0] != '@' {
|
if data[0] != '@' {
|
||||||
|
@ -3,6 +3,7 @@ package curl2info
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,7 +48,10 @@ func TestTouTiaoCURL(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
t.Log(curl, "Content:\n", resp.Content())
|
|
||||||
|
if !regexp.MustCompile(`"data".*comment_count.*"context"`).Match([]byte(resp.Content())) {
|
||||||
|
t.Error(curl, resp.Content())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorCurl(t *testing.T) {
|
func TestErrorCurl(t *testing.T) {
|
||||||
@ -63,7 +67,10 @@ func TestErrorCurl(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
t.Log("Content:\n", resp.Content(), reflect.TypeOf(curl.Body.GetIOBody()))
|
|
||||||
|
if !regexp.MustCompile(`App Growing`).Match([]byte(resp.Content())) {
|
||||||
|
t.Error(resp.Content(), curl, reflect.TypeOf(curl.Body.GetIOBody()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCurlTimeout(t *testing.T) {
|
func TestCurlTimeout(t *testing.T) {
|
||||||
|
157
structure.go
Normal file
157
structure.go
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
package curl2info
|
||||||
|
|
||||||
|
// TrieWord Trie 需要的Word接口
|
||||||
|
type TrieWord interface {
|
||||||
|
GetWord() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrieStrWord 最简单的TrieWord 结构
|
||||||
|
type TrieStrWord string
|
||||||
|
|
||||||
|
// GetWord 获取单词
|
||||||
|
func (tsw *TrieStrWord) GetWord() string {
|
||||||
|
return (string)(*tsw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trie 前缀树
|
||||||
|
type Trie struct {
|
||||||
|
isWord bool
|
||||||
|
value interface{}
|
||||||
|
char byte
|
||||||
|
prev *Trie
|
||||||
|
next map[byte]*Trie
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTrie Initialize your data structure here.
|
||||||
|
func NewTrie() *Trie {
|
||||||
|
return &Trie{next: make(map[byte]*Trie)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert a word into the trie.
|
||||||
|
func (trie *Trie) Insert(iword TrieWord) {
|
||||||
|
cur := trie
|
||||||
|
word := iword.GetWord()
|
||||||
|
l := len(word)
|
||||||
|
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
c := word[i]
|
||||||
|
if next, ok := cur.next[c]; ok {
|
||||||
|
cur = next
|
||||||
|
} else {
|
||||||
|
create := NewTrie()
|
||||||
|
cur.next[c] = create
|
||||||
|
create.char = c
|
||||||
|
create.prev = cur
|
||||||
|
cur = create
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur.isWord = true
|
||||||
|
cur.value = iword
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllWords 所有单词
|
||||||
|
func (trie *Trie) AllWords() []string {
|
||||||
|
var result []string
|
||||||
|
for _, v := range trie.next {
|
||||||
|
look(v, "", &result)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func look(cur *Trie, content string, result *[]string) {
|
||||||
|
content += string(cur.char)
|
||||||
|
if cur.isWord {
|
||||||
|
*result = append(*result, content)
|
||||||
|
}
|
||||||
|
for _, v := range cur.next {
|
||||||
|
look(v, content, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove 移除单词
|
||||||
|
func (trie *Trie) Remove(word string) {
|
||||||
|
cur := trie
|
||||||
|
l := len(word)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
c := word[i]
|
||||||
|
if next, ok := cur.next[c]; ok {
|
||||||
|
cur = next
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cur != nil {
|
||||||
|
cur.isWord = false
|
||||||
|
cur.value = nil
|
||||||
|
|
||||||
|
lastchar := cur.char
|
||||||
|
|
||||||
|
if len(cur.next) == 0 {
|
||||||
|
for cur.isWord != true && cur.prev != nil {
|
||||||
|
lastchar = cur.char
|
||||||
|
cur = cur.prev
|
||||||
|
if len(cur.next) > 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(cur.next, lastchar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchMostPrefix Returns if the word is in the trie.
|
||||||
|
func (trie *Trie) SearchMostPrefix(iword TrieWord) interface{} {
|
||||||
|
cur := trie
|
||||||
|
word := iword.GetWord()
|
||||||
|
|
||||||
|
l := len(word)
|
||||||
|
|
||||||
|
var result interface{}
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
c := word[i]
|
||||||
|
if next, ok := cur.next[c]; ok {
|
||||||
|
cur = next
|
||||||
|
if cur.isWord {
|
||||||
|
result = cur.value
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match Returns if the word is in the trie.
|
||||||
|
func (trie *Trie) Match(iword TrieWord) interface{} {
|
||||||
|
cur := trie
|
||||||
|
word := iword.GetWord()
|
||||||
|
|
||||||
|
l := len(word)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
c := word[i]
|
||||||
|
if next, ok := cur.next[c]; ok {
|
||||||
|
cur = next
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartsWith Returns if there is any word in the trie that starts with the given prefix. */
|
||||||
|
func (trie *Trie) StartsWith(prefix string) bool {
|
||||||
|
cur := trie
|
||||||
|
l := len(prefix)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
c := prefix[i]
|
||||||
|
if next, ok := cur.next[c]; ok {
|
||||||
|
cur = next
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
1
structure_test.go
Normal file
1
structure_test.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package curl2info
|
Loading…
x
Reference in New Issue
Block a user