diff options
| author | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2024-06-15 13:58:30 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-15 13:58:30 +0300 |
| commit | 77e4b066cb8d506b4bc944ab4eb2d6e4679e2202 (patch) | |
| tree | 1d549eca619ed36cb881e487cb054c4643ac8376 /cmd/parser.go | |
| parent | change project name to sdp.go (diff) | |
| download | sdp.go-77e4b066cb8d506b4bc944ab4eb2d6e4679e2202.tar.gz sdp.go-77e4b066cb8d506b4bc944ab4eb2d6e4679e2202.tar.bz2 sdp.go-77e4b066cb8d506b4bc944ab4eb2d6e4679e2202.zip | |
enable multithreading with goroutines (#20)
Diffstat (limited to 'cmd/parser.go')
| -rw-r--r-- | cmd/parser.go | 79 |
1 files changed, 46 insertions, 33 deletions
diff --git a/cmd/parser.go b/cmd/parser.go index f21d91f..06ebbfe 100644 --- a/cmd/parser.go +++ b/cmd/parser.go | |||
| @@ -4,21 +4,17 @@ import ( | |||
| 4 | "errors" | 4 | "errors" |
| 5 | "fmt" | 5 | "fmt" |
| 6 | "os" | 6 | "os" |
| 7 | "strings" | 7 | "path/filepath" |
| 8 | "sync" | ||
| 8 | 9 | ||
| 9 | "github.com/pektezol/bitreader" | 10 | "github.com/pektezol/bitreader" |
| 10 | "github.com/pektezol/sdp.go/pkg/packets" | 11 | "github.com/pektezol/sdp.go/pkg/packets" |
| 12 | "github.com/pektezol/sdp.go/pkg/types" | ||
| 11 | "github.com/pektezol/sdp.go/pkg/writer" | 13 | "github.com/pektezol/sdp.go/pkg/writer" |
| 12 | ) | 14 | ) |
| 13 | 15 | ||
| 14 | type Demo struct { | ||
| 15 | Headers packets.Headers `json:"headers"` | ||
| 16 | Messages []packets.Message `json:"messages"` | ||
| 17 | } | ||
| 18 | |||
| 19 | type Parser struct { | 16 | type Parser struct { |
| 20 | DemoPath string | 17 | DemoPath string |
| 21 | writer strings.Builder | ||
| 22 | } | 18 | } |
| 23 | 19 | ||
| 24 | func NewParser(demoPath string) *Parser { | 20 | func NewParser(demoPath string) *Parser { |
| @@ -35,48 +31,61 @@ func main() { | |||
| 35 | os.Exit(1) | 31 | os.Exit(1) |
| 36 | } | 32 | } |
| 37 | parser := NewParser(os.Args[1]) | 33 | parser := NewParser(os.Args[1]) |
| 38 | _, err := parser.ParseDemos() | 34 | demos, err := parser.ParseDemos() |
| 39 | if err != nil { | 35 | if err != nil { |
| 40 | fmt.Println(err.Error()) | 36 | fmt.Println(err.Error()) |
| 41 | os.Exit(1) | 37 | os.Exit(1) |
| 42 | } | 38 | } |
| 43 | fmt.Println(parser.GetOutput()) | 39 | for _, d := range demos { |
| 44 | } | 40 | fmt.Println(d.Writer.GetOutputString()) |
| 45 | 41 | // You can also marshal structs into JSON and print them: | |
| 46 | func (p *Parser) GetOutput() string { | 42 | // out, _ := json.Marshal(d) |
| 47 | return p.writer.String() | 43 | // fmt.Println(string(out)) |
| 44 | } | ||
| 48 | } | 45 | } |
| 49 | 46 | ||
| 50 | func (p *Parser) ParseDemos() ([]Demo, error) { | 47 | func (p *Parser) ParseDemos() ([]*types.Demo, error) { |
| 51 | writer.AppendLine("Generated By: github.com/pektezol/sdp.go") | ||
| 52 | files, err := os.ReadDir(p.DemoPath) | 48 | files, err := os.ReadDir(p.DemoPath) |
| 53 | if err != nil { | 49 | if err != nil { |
| 54 | // not a directory | 50 | // not a directory |
| 55 | file, err := os.Open(p.DemoPath) | 51 | file, err := os.Open(p.DemoPath) |
| 56 | if err != nil { | 52 | if err != nil { |
| 57 | return []Demo{}, err | 53 | return []*types.Demo{}, err |
| 58 | } | 54 | } |
| 59 | defer file.Close() | 55 | defer file.Close() |
| 56 | demo := &types.Demo{} | ||
| 57 | demo.Writer = writer.NewWriter() | ||
| 58 | demo.Writer.AppendLine("Generated By: github.com/pektezol/sdp.go") | ||
| 60 | reader := bitreader.NewReader(file, littleEndian) | 59 | reader := bitreader.NewReader(file, littleEndian) |
| 61 | demo := demoParserHandler(reader, file.Name()) | 60 | p.demoParserHandler(reader, file.Name(), demo, nil) |
| 62 | p.writer = writer.GetWriter() | 61 | return []*types.Demo{demo}, nil |
| 63 | return []Demo{demo}, nil | ||
| 64 | } else { | 62 | } else { |
| 65 | demos := []Demo{} | ||
| 66 | // directory | 63 | // directory |
| 64 | demoCount := 0 | ||
| 67 | for _, fileinfo := range files { | 65 | for _, fileinfo := range files { |
| 68 | if len(fileinfo.Name()) > 4 && fileinfo.Name()[len(fileinfo.Name())-4:] == ".dem" { | 66 | if len(fileinfo.Name()) > 4 && fileinfo.Name()[len(fileinfo.Name())-4:] == ".dem" { |
| 69 | file, err := os.Open(p.DemoPath + fileinfo.Name()) | 67 | demoCount++ |
| 68 | } | ||
| 69 | } | ||
| 70 | wg := new(sync.WaitGroup) | ||
| 71 | wg.Add(demoCount) | ||
| 72 | demos := make([]*types.Demo, demoCount) | ||
| 73 | for i := 0; i < len(demos); i++ { | ||
| 74 | demos[i] = &types.Demo{} | ||
| 75 | demos[i].Writer = writer.NewWriter() | ||
| 76 | demos[i].Writer.AppendLine("Generated By: github.com/pektezol/sdp.go") | ||
| 77 | } | ||
| 78 | for i, fileinfo := range files { | ||
| 79 | if len(fileinfo.Name()) > 4 && fileinfo.Name()[len(fileinfo.Name())-4:] == ".dem" { | ||
| 80 | file, err := os.Open(filepath.Join(p.DemoPath, fileinfo.Name())) | ||
| 70 | if err != nil { | 81 | if err != nil { |
| 71 | return []Demo{}, err | 82 | return []*types.Demo{}, err |
| 72 | } | 83 | } |
| 73 | defer file.Close() | 84 | defer file.Close() |
| 74 | reader := bitreader.NewReader(file, littleEndian) | 85 | go p.demoParserHandler(bitreader.NewReader(file, littleEndian), file.Name(), demos[i], wg) |
| 75 | demo := demoParserHandler(reader, file.Name()) | ||
| 76 | demos = append(demos, demo) | ||
| 77 | } | 86 | } |
| 78 | } | 87 | } |
| 79 | p.writer = writer.GetWriter() | 88 | wg.Wait() |
| 80 | if len(demos) == 0 { | 89 | if len(demos) == 0 { |
| 81 | return demos, errors.New("no demo found in given directory") | 90 | return demos, errors.New("no demo found in given directory") |
| 82 | } | 91 | } |
| @@ -84,23 +93,27 @@ func (p *Parser) ParseDemos() ([]Demo, error) { | |||
| 84 | } | 93 | } |
| 85 | } | 94 | } |
| 86 | 95 | ||
| 87 | func demoParserHandler(reader *bitreader.Reader, filename string) Demo { | 96 | func (p *Parser) demoParserHandler(reader *bitreader.Reader, filename string, demo *types.Demo, wg *sync.WaitGroup) { |
| 88 | demo := Demo{} | 97 | demo.Writer.AppendLine("\nFile Name: %s", filename) |
| 89 | writer.AppendLine("\nFile Name: %s", filename) | ||
| 90 | // this is for recovering after a panic inside parse headers and packet. | 98 | // this is for recovering after a panic inside parse headers and packet. |
| 91 | // this approach was taken since error handling bitreader functions would take a long time. | 99 | // this approach was taken since error handling bitreader functions would take a long time. |
| 92 | defer func() { | 100 | defer func() { |
| 93 | if err := recover(); err != nil { | 101 | if err := recover(); err != nil { |
| 94 | writer.AppendLine("failed to parse demo: %v", err) | 102 | if wg != nil { |
| 103 | wg.Done() | ||
| 104 | } | ||
| 105 | demo.Writer.AppendLine("failed to parse demo: %v", err) | ||
| 95 | } | 106 | } |
| 96 | }() | 107 | }() |
| 97 | demo.Headers = packets.ParseHeaders(reader) | 108 | demo.Headers = packets.ParseHeaders(reader, demo) |
| 98 | for { | 109 | for { |
| 99 | message := packets.ParseMessage(reader) | 110 | message := packets.ParseMessage(reader, demo) |
| 100 | demo.Messages = append(demo.Messages, message) | 111 | demo.Messages = append(demo.Messages, message) |
| 101 | if message.PacketType == 7 { | 112 | if message.PacketType == 7 { |
| 113 | if wg != nil { | ||
| 114 | wg.Done() | ||
| 115 | } | ||
| 102 | break | 116 | break |
| 103 | } | 117 | } |
| 104 | } | 118 | } |
| 105 | return demo | ||
| 106 | } | 119 | } |