diff --git a/base.go b/base.go index 810a7cd..4591616 100644 --- a/base.go +++ b/base.go @@ -1 +1,84 @@ package curl2info + +import ( + "container/heap" +) + +// Nodes for Heap, Container List +type Nodes []*ParseFunction + +// ParseFunction 优先执行参数 +type ParseFunction struct { + ExecuteFunction func(u *CURL, soption string) + ParamCURL *CURL + ParamData string + Prioty int +} + +// Swap 实现sort.Iterface +func (nodes *Nodes) Swap(i, j int) { + ns := *nodes + ns[i], ns[j] = ns[j], ns[i] +} + +// Less Priority Want Less +func (nodes *Nodes) Less(i, j int) bool { + ns := *nodes + return ns[i].Prioty < ns[j].Prioty +} + +// Push 实现heap.Interface接口定义的额外方法 +func (nodes *Nodes) Push(exec interface{}) { + *nodes = append(*nodes, exec.(*ParseFunction)) +} + +// Pop 堆顶 +func (nodes *Nodes) Pop() (exec interface{}) { + nlen := nodes.Len() + exec = (*nodes)[nlen-1] // 返回删除的元素 + *nodes = (*nodes)[:nlen-1] // [n:m]不包括下标为m的元素 + return exec +} + +// Len len(nodes) +func (nodes *Nodes) Len() int { + return len(*nodes) +} + +// PQueueExecute 优先函数队列 +type PQueueExecute struct { + nodes Nodes +} + +// NewPQueueExecute Create A PQueueExecute +func NewPQueueExecute() *PQueueExecute { + pe := &PQueueExecute{} + pe.nodes = make(Nodes, 0) + heap.Init(&pe.nodes) + return pe +} + +// Push Create A PQueueExecute +func (pqe *PQueueExecute) Push(exec *ParseFunction) { + heap.Push(&pqe.nodes, exec) + heap.Fix(&pqe.nodes, pqe.Len()-1) +} + +// Pop Create A PQueueExecute +func (pqe *PQueueExecute) Pop() *ParseFunction { + return heap.Pop(&pqe.nodes).(*ParseFunction) +} + +// Len Create A PQueueExecute +func (pqe *PQueueExecute) Len() int { + return pqe.nodes.Len() +} + +// func (pqe *PQueueExecute) String() string { +// content := "" +// for _, node := range pqe.nodes { +// content += strconv.Itoa(node.Prioty) +// content += " " +// } +// return content +// } diff --git a/base_test.go b/base_test.go new file mode 100644 index 0000000..9b56165 --- /dev/null +++ b/base_test.go @@ -0,0 +1,26 @@ +package curl2info + +import ( + "strconv" + "testing" +) + +func TestPQueue(t *testing.T) { + PQExec := NewPQueueExecute() + PQExec.Push(&ParseFunction{Prioty: 5}) + PQExec.Push(&ParseFunction{Prioty: 10}) + PQExec.Push(&ParseFunction{Prioty: 4}) + PQExec.Push(&ParseFunction{Prioty: 4}) + PQExec.Push(&ParseFunction{Prioty: 20}) + PQExec.Push(&ParseFunction{Prioty: 10}) + PQExec.Push(&ParseFunction{Prioty: 15}) + + content := "" + for PQExec.Len() > 0 { + content += strconv.Itoa(PQExec.Pop().Prioty) + content += " " + } + if content != "4 4 5 10 10 15 20 " { + t.Error(content) + } +} diff --git a/parse_curl.go b/parse_curl.go index 338a38c..78c5e88 100644 --- a/parse_curl.go +++ b/parse_curl.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "io/ioutil" + "log" "net/http" "net/http/cookiejar" "net/url" @@ -120,14 +121,6 @@ func ParseRawCURL(scurl string) (cURL *CURL, err error) { return curl, nil } -// ParseFunction 优先执行参数 -type ParseFunction struct { - ExecuteFunction func(u *CURL, soption string) - ParamCURL *CURL - ParamData string - Prioty int -} - func judgeAndParseOptions(u *CURL, soption string) *ParseFunction { switch prefix := soption[0:2]; prefix { case "-H": @@ -135,21 +128,16 @@ func judgeAndParseOptions(u *CURL, soption string) *ParseFunction { case "-X": return &ParseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseOptX, Prioty: 1} case "-A": // User-Agent 先后顺序的问题 - parseHeader(u, soption) + return &ParseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseHeader, Prioty: 1} case "-I": - u.Method = "HEAD" + return &ParseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseOptI, Prioty: 1} case "--": - parseLongOption(u, soption) + return parseLongOption(u, soption) } + return nil } -func parseOptX(u *CURL, soption string) { - matches := regexp.MustCompile("-X +(.+)").FindStringSubmatch(soption) - method := strings.Trim(matches[1], "'") - u.Method = method -} - -func parseLongOption(u *CURL, soption string) { +func parseLongOption(u *CURL, soption string) *ParseFunction { // -d, --data HTTP POST data // --data-ascii HTTP POST ASCII data // --data-binary HTTP POST binary data @@ -169,20 +157,32 @@ func parseLongOption(u *CURL, soption string) { switch dtype { case "binary": - parseBodyBinary(u, data) + return &ParseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyBinary, Prioty: 1} case "ascii": - parseBodyASCII(u, data) + return &ParseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyASCII, Prioty: 1} case "raw": - parseBodyRaw(u, data) + return &ParseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyRaw, Prioty: 1} case "urlencode": - parseBodyURLEncode(u, data) + return &ParseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyURLEncode, Prioty: 1} case "data": - parseBodyASCII(u, data) + return &ParseFunction{ParamCURL: u, ParamData: data, ExecuteFunction: parseBodyASCII, Prioty: 1} } case regexp.MustCompile("^--header").MatchString(soption): - parseHeader(u, soption) + return &ParseFunction{ParamCURL: u, ParamData: soption, ExecuteFunction: parseHeader, Prioty: 1} } + log.Println("can't parseOption", soption) + return nil +} + +func parseOptI(u *CURL, soption string) { + u.Method = "HEAD" +} + +func parseOptX(u *CURL, soption string) { + matches := regexp.MustCompile("-X +(.+)").FindStringSubmatch(soption) + method := strings.Trim(matches[1], "'") + u.Method = method } func parseBodyURLEncode(u *CURL, data string) {