Przeglądaj źródła

refactor cap line splitting

tags/v1.2.0
Shivaram Lingamneni 4 lat temu
rodzic
commit
a75d26a46b
5 zmienionych plików z 126 dodań i 83 usunięć
  1. 1
    0
      gencapdefs.py
  2. 52
    52
      irc/caps/defs.go
  3. 8
    31
      irc/caps/set.go
  4. 41
    0
      irc/utils/text.go
  5. 24
    0
      irc/utils/text_test.go

+ 1
- 0
gencapdefs.py Wyświetl plik

@@ -180,6 +180,7 @@ CAPDEFS = [
180 180
 ]
181 181
 
182 182
 def validate_defs():
183
+    CAPDEFS.sort(key=lambda d: d.name)
183 184
     numCaps = len(CAPDEFS)
184 185
     numNames = len(set(capdef.name for capdef in CAPDEFS))
185 186
     if numCaps != numNames:

+ 52
- 52
irc/caps/defs.go Wyświetl plik

@@ -13,10 +13,6 @@ const (
13 13
 )
14 14
 
15 15
 const (
16
-	// Acc is the proposed IRCv3 capability named "draft/acc":
17
-	// https://github.com/ircv3/ircv3-specifications/pull/276
18
-	Acc Capability = iota
19
-
20 16
 	// AccountNotify is the IRCv3 capability named "account-notify":
21 17
 	// https://ircv3.net/specs/extensions/account-notify-3.1.html
22 18
 	AccountNotify Capability = iota
@@ -41,6 +37,34 @@ const (
41 37
 	// https://ircv3.net/specs/extensions/chghost-3.2.html
42 38
 	ChgHost Capability = iota
43 39
 
40
+	// Acc is the proposed IRCv3 capability named "draft/acc":
41
+	// https://github.com/ircv3/ircv3-specifications/pull/276
42
+	Acc Capability = iota
43
+
44
+	// EventPlayback is the Proposed IRCv3 capability named "draft/event-playback":
45
+	// https://github.com/ircv3/ircv3-specifications/pull/362
46
+	EventPlayback Capability = iota
47
+
48
+	// LabeledResponse is the draft IRCv3 capability named "draft/labeled-response-0.2":
49
+	// https://ircv3.net/specs/extensions/labeled-response.html
50
+	LabeledResponse Capability = iota
51
+
52
+	// Languages is the proposed IRCv3 capability named "draft/languages":
53
+	// https://gist.github.com/DanielOaks/8126122f74b26012a3de37db80e4e0c6
54
+	Languages Capability = iota
55
+
56
+	// Rename is the proposed IRCv3 capability named "draft/rename":
57
+	// https://github.com/SaberUK/ircv3-specifications/blob/rename/extensions/rename.md
58
+	Rename Capability = iota
59
+
60
+	// Resume is the proposed IRCv3 capability named "draft/resume-0.5":
61
+	// https://github.com/DanielOaks/ircv3-specifications/blob/master+resume/extensions/resume.md
62
+	Resume Capability = iota
63
+
64
+	// SetName is the proposed IRCv3 capability named "draft/setname":
65
+	// https://github.com/ircv3/ircv3-specifications/pull/361
66
+	SetName Capability = iota
67
+
44 68
 	// EchoMessage is the IRCv3 capability named "echo-message":
45 69
 	// https://ircv3.net/specs/extensions/echo-message-3.2.html
46 70
 	EchoMessage Capability = iota
@@ -53,18 +77,6 @@ const (
53 77
 	// https://ircv3.net/specs/extensions/invite-notify-3.2.html
54 78
 	InviteNotify Capability = iota
55 79
 
56
-	// LabeledResponse is the draft IRCv3 capability named "draft/labeled-response-0.2":
57
-	// https://ircv3.net/specs/extensions/labeled-response.html
58
-	LabeledResponse Capability = iota
59
-
60
-	// Languages is the proposed IRCv3 capability named "draft/languages":
61
-	// https://gist.github.com/DanielOaks/8126122f74b26012a3de37db80e4e0c6
62
-	Languages Capability = iota
63
-
64
-	// MaxLine is the Oragono-specific capability named "oragono.io/maxline-2":
65
-	// https://oragono.io/maxline-2
66
-	MaxLine Capability = iota
67
-
68 80
 	// MessageTags is the IRCv3 capability named "message-tags":
69 81
 	// https://ircv3.net/specs/extensions/message-tags.html
70 82
 	MessageTags Capability = iota
@@ -73,13 +85,17 @@ const (
73 85
 	// https://ircv3.net/specs/extensions/multi-prefix-3.1.html
74 86
 	MultiPrefix Capability = iota
75 87
 
76
-	// Rename is the proposed IRCv3 capability named "draft/rename":
77
-	// https://github.com/SaberUK/ircv3-specifications/blob/rename/extensions/rename.md
78
-	Rename Capability = iota
88
+	// Bouncer is the Oragono-specific capability named "oragono.io/bnc":
89
+	// https://oragono.io/bnc
90
+	Bouncer Capability = iota
79 91
 
80
-	// Resume is the proposed IRCv3 capability named "draft/resume-0.5":
81
-	// https://github.com/DanielOaks/ircv3-specifications/blob/master+resume/extensions/resume.md
82
-	Resume Capability = iota
92
+	// MaxLine is the Oragono-specific capability named "oragono.io/maxline-2":
93
+	// https://oragono.io/maxline-2
94
+	MaxLine Capability = iota
95
+
96
+	// Nope is the Oragono vendor capability named "oragono.io/nope":
97
+	// https://oragono.io/nope
98
+	Nope Capability = iota
83 99
 
84 100
 	// SASL is the IRCv3 capability named "sasl":
85 101
 	// https://ircv3.net/specs/extensions/sasl-3.2.html
@@ -89,10 +105,6 @@ const (
89 105
 	// https://ircv3.net/specs/extensions/server-time-3.2.html
90 106
 	ServerTime Capability = iota
91 107
 
92
-	// SetName is the proposed IRCv3 capability named "draft/setname":
93
-	// https://github.com/ircv3/ircv3-specifications/pull/361
94
-	SetName Capability = iota
95
-
96 108
 	// STS is the IRCv3 capability named "sts":
97 109
 	// https://ircv3.net/specs/extensions/sts.html
98 110
 	STS Capability = iota
@@ -101,56 +113,44 @@ const (
101 113
 	// https://ircv3.net/specs/extensions/userhost-in-names-3.2.html
102 114
 	UserhostInNames Capability = iota
103 115
 
104
-	// Bouncer is the Oragono-specific capability named "oragono.io/bnc":
105
-	// https://oragono.io/bnc
106
-	Bouncer Capability = iota
107
-
108
-	// ZNCSelfMessage is the ZNC vendor capability named "znc.in/self-message":
109
-	// https://wiki.znc.in/Query_buffers
110
-	ZNCSelfMessage Capability = iota
111
-
112
-	// EventPlayback is the Proposed IRCv3 capability named "draft/event-playback":
113
-	// https://github.com/ircv3/ircv3-specifications/pull/362
114
-	EventPlayback Capability = iota
115
-
116 116
 	// ZNCPlayback is the ZNC vendor capability named "znc.in/playback":
117 117
 	// https://wiki.znc.in/Playback
118 118
 	ZNCPlayback Capability = iota
119 119
 
120
-	// Nope is the Oragono vendor capability named "oragono.io/nope":
121
-	// https://oragono.io/nope
122
-	Nope Capability = iota
120
+	// ZNCSelfMessage is the ZNC vendor capability named "znc.in/self-message":
121
+	// https://wiki.znc.in/Query_buffers
122
+	ZNCSelfMessage Capability = iota
123 123
 )
124 124
 
125 125
 // `capabilityNames[capab]` is the string name of the capability `capab`
126 126
 var (
127 127
 	capabilityNames = [numCapabs]string{
128
-		"draft/acc",
129 128
 		"account-notify",
130 129
 		"account-tag",
131 130
 		"away-notify",
132 131
 		"batch",
133 132
 		"cap-notify",
134 133
 		"chghost",
134
+		"draft/acc",
135
+		"draft/event-playback",
136
+		"draft/labeled-response-0.2",
137
+		"draft/languages",
138
+		"draft/rename",
139
+		"draft/resume-0.5",
140
+		"draft/setname",
135 141
 		"echo-message",
136 142
 		"extended-join",
137 143
 		"invite-notify",
138
-		"draft/labeled-response-0.2",
139
-		"draft/languages",
140
-		"oragono.io/maxline-2",
141 144
 		"message-tags",
142 145
 		"multi-prefix",
143
-		"draft/rename",
144
-		"draft/resume-0.5",
146
+		"oragono.io/bnc",
147
+		"oragono.io/maxline-2",
148
+		"oragono.io/nope",
145 149
 		"sasl",
146 150
 		"server-time",
147
-		"draft/setname",
148 151
 		"sts",
149 152
 		"userhost-in-names",
150
-		"oragono.io/bnc",
151
-		"znc.in/self-message",
152
-		"draft/event-playback",
153 153
 		"znc.in/playback",
154
-		"oragono.io/nope",
154
+		"znc.in/self-message",
155 155
 	}
156 156
 )

+ 8
- 31
irc/caps/set.go Wyświetl plik

@@ -4,9 +4,7 @@
4 4
 package caps
5 5
 
6 6
 import (
7
-	"bytes"
8
-	"sort"
9
-
7
+	"fmt"
10 8
 	"github.com/oragono/oragono/irc/utils"
11 9
 )
12 10
 
@@ -95,7 +93,8 @@ const maxPayloadLength = 440
95 93
 
96 94
 // Strings returns all of our enabled capabilities as a slice of strings.
97 95
 func (s *Set) Strings(version Version, values Values) (result []string) {
98
-	var strs sort.StringSlice
96
+	var t utils.TokenLineBuilder
97
+	t.Initialize(maxPayloadLength, " ")
99 98
 
100 99
 	var capab Capability
101 100
 	asSlice := s[:]
@@ -108,37 +107,15 @@ func (s *Set) Strings(version Version, values Values) (result []string) {
108 107
 		if version >= Cap302 {
109 108
 			val, exists := values[capab]
110 109
 			if exists {
111
-				capString += "=" + val
110
+				capString = fmt.Sprintf("%s=%s", capString, val)
112 111
 			}
113 112
 		}
114
-		strs = append(strs, capString)
113
+		t.Add(capString)
115 114
 	}
116 115
 
117
-	if len(strs) == 0 {
118
-		return []string{""}
116
+	result = t.Lines()
117
+	if result == nil {
118
+		result = []string{""}
119 119
 	}
120
-
121
-	// sort the cap string before we send it out
122
-	sort.Sort(strs)
123
-
124
-	var buf bytes.Buffer
125
-	for _, str := range strs {
126
-		tokenLen := len(str)
127
-		if buf.Len() != 0 {
128
-			tokenLen += 1
129
-		}
130
-		if maxPayloadLength < buf.Len()+tokenLen {
131
-			result = append(result, buf.String())
132
-			buf.Reset()
133
-		}
134
-		if buf.Len() != 0 {
135
-			buf.WriteByte(' ')
136
-		}
137
-		buf.WriteString(str)
138
-	}
139
-	if buf.Len() != 0 {
140
-		result = append(result, buf.String())
141
-	}
142
-
143 120
 	return
144 121
 }

+ 41
- 0
irc/utils/text.go Wyświetl plik

@@ -83,3 +83,44 @@ func MakeSplitMessage(original string, origIs512 bool) (result SplitMessage) {
83 83
 
84 84
 	return
85 85
 }
86
+
87
+// TokenLineBuilder is a helper for building IRC lines composed of delimited tokens,
88
+// with a maximum line length.
89
+type TokenLineBuilder struct {
90
+	lineLen int
91
+	delim   string
92
+	buf     bytes.Buffer
93
+	result  []string
94
+}
95
+
96
+func (t *TokenLineBuilder) Initialize(lineLen int, delim string) {
97
+	t.lineLen = lineLen
98
+	t.delim = delim
99
+}
100
+
101
+// Add adds a token to the line, creating a new line if necessary.
102
+func (t *TokenLineBuilder) Add(token string) {
103
+	tokenLen := len(token)
104
+	if t.buf.Len() != 0 {
105
+		tokenLen += len(t.delim)
106
+	}
107
+	if t.lineLen < t.buf.Len()+tokenLen {
108
+		t.result = append(t.result, t.buf.String())
109
+		t.buf.Reset()
110
+	}
111
+	if t.buf.Len() != 0 {
112
+		t.buf.WriteString(t.delim)
113
+	}
114
+	t.buf.WriteString(token)
115
+}
116
+
117
+// Lines terminates the line-building and returns all the lines.
118
+func (t *TokenLineBuilder) Lines() (result []string) {
119
+	result = t.result
120
+	t.result = nil
121
+	if t.buf.Len() != 0 {
122
+		result = append(result, t.buf.String())
123
+		t.buf.Reset()
124
+	}
125
+	return
126
+}

+ 24
- 0
irc/utils/text_test.go Wyświetl plik

@@ -58,3 +58,27 @@ func BenchmarkWordWrap(b *testing.B) {
58 58
 		WordWrap(monteCristo, 60)
59 59
 	}
60 60
 }
61
+
62
+func TestTokenLineBuilder(t *testing.T) {
63
+	lineLen := 400
64
+	var tl TokenLineBuilder
65
+	tl.Initialize(lineLen, " ")
66
+	for _, token := range strings.Fields(monteCristo) {
67
+		tl.Add(token)
68
+	}
69
+
70
+	lines := tl.Lines()
71
+	if len(lines) != 4 {
72
+		t.Errorf("expected 4 lines, got %d", len(lines))
73
+	}
74
+	for _, line := range lines {
75
+		if len(line) > lineLen {
76
+			t.Errorf("line length %d exceeds maximum of %d", len(line), lineLen)
77
+		}
78
+	}
79
+
80
+	joined := strings.Join(lines, " ")
81
+	if joined != monteCristo {
82
+		t.Errorf("text incorrectly split into lines: %s instead of %s", joined, monteCristo)
83
+	}
84
+}

Ładowanie…
Anuluj
Zapisz