aboutsummaryrefslogtreecommitdiff
path: root/cmd/parser.go
diff options
context:
space:
mode:
authorArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2024-06-15 13:58:30 +0300
committerGitHub <noreply@github.com>2024-06-15 13:58:30 +0300
commit77e4b066cb8d506b4bc944ab4eb2d6e4679e2202 (patch)
tree1d549eca619ed36cb881e487cb054c4643ac8376 /cmd/parser.go
parentchange project name to sdp.go (diff)
downloadsdp.go-77e4b066cb8d506b4bc944ab4eb2d6e4679e2202.tar.gz
sdp.go-77e4b066cb8d506b4bc944ab4eb2d6e4679e2202.tar.bz2
sdp.go-77e4b066cb8d506b4bc944ab4eb2d6e4679e2202.zip
enable multithreading with goroutines (#20)
Diffstat (limited to '')
-rw-r--r--cmd/parser.go79
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
14type Demo struct {
15 Headers packets.Headers `json:"headers"`
16 Messages []packets.Message `json:"messages"`
17}
18
19type Parser struct { 16type Parser struct {
20 DemoPath string 17 DemoPath string
21 writer strings.Builder
22} 18}
23 19
24func NewParser(demoPath string) *Parser { 20func 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:
46func (p *Parser) GetOutput() string { 42 // out, _ := json.Marshal(d)
47 return p.writer.String() 43 // fmt.Println(string(out))
44 }
48} 45}
49 46
50func (p *Parser) ParseDemos() ([]Demo, error) { 47func (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
87func demoParserHandler(reader *bitreader.Reader, filename string) Demo { 96func (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}