Bladeren bron

Make IRCStringConverter use an enum sensibly

Fixes CLIENT-135

Change-Id: I5f326523ff031c0996996f0efad6c8e5d7278c7f
Reviewed-on: http://gerrit.dmdirc.com/1859
Automatic-Compile: DMDirc Local Commits <dmdirc@googlemail.com>
Reviewed-by: Greg Holmes <greg@dmdirc.com>
tags/0.7rc1
Chris Smith 13 jaren geleden
bovenliggende
commit
ba65d14741

+ 62
- 0
src/com/dmdirc/parser/irc/IRCEncoding.java Bestand weergeven

@@ -0,0 +1,62 @@
1
+/*
2
+ * Copyright (c) 2006-2011 Chris Smith, Shane Mc Cormack, Gregory Holmes
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.parser.irc;
24
+
25
+/**
26
+ * An enumeration of the supported types of encoding for an IRC connection.
27
+ *
28
+ * @since 0.6.6
29
+ */
30
+public enum IRCEncoding {
31
+
32
+    /** The ASCII encoding. */
33
+    ASCII(0),
34
+    /** "Strict" RFC1459. */
35
+    STRICT_RFC1459(3),
36
+    /** Standard RFC1459. */
37
+    RFC1459(4);
38
+
39
+    /** The limit used for this encoding. */
40
+    private final int limit;
41
+
42
+    /**
43
+     * Creates a new instance of IRCEncoding with the specified limit.
44
+     *
45
+     * @param limit The limit used for this encoding.
46
+     */
47
+    private IRCEncoding(final int limit) {
48
+        this.limit = limit;
49
+    }
50
+
51
+    /**
52
+     * Retrieves the "limit" of this encoding. That is, the number of characters
53
+     * after the uppercase ASCII 'Z' which should be treated
54
+     * "case-insensitively". A limit of 3 will cause the '[', '\' and ']'
55
+     * characters to be treated as equal to '{', '|' and '}', respectively.
56
+     *
57
+     * @return The limit of this encoding
58
+     */
59
+    public int getLimit() {
60
+        return limit;
61
+    }
62
+}

+ 6
- 10
src/com/dmdirc/parser/irc/IRCParser.java Bestand weergeven

@@ -712,8 +712,7 @@ public class IRCParser implements SecureParser, EncodingParser, Runnable {
712 712
         stopPingTimer();
713 713
 
714 714
         currentSocketState = SocketState.CLOSED;
715
-        // Char Mapping
716
-        updateCharArrays((byte) 4);
715
+        setEncoding(IRCEncoding.RFC1459);
717 716
     }
718 717
 
719 718
     /**
@@ -1201,21 +1200,18 @@ public class IRCParser implements SecureParser, EncodingParser, Runnable {
1201 1200
     @Override
1202 1201
     public IRCStringConverter getStringConverter() {
1203 1202
         if (stringConverter == null) {
1204
-            stringConverter = new IRCStringConverter((byte) 4);
1203
+            stringConverter = new IRCStringConverter(IRCEncoding.RFC1459);
1205 1204
         }
1206 1205
         return stringConverter;
1207 1206
     }
1208 1207
 
1209 1208
     /**
1210
-     * Update the character arrays.
1209
+     * Sets the encoding that this parser's string converter should use.
1211 1210
      *
1212
-     * @param limit Number of post-alphabetical characters to convert
1213
-     *              0 = ascii encoding
1214
-     *              3 = strict-rfc1459 encoding
1215
-     *              4 = rfc1459 encoding
1211
+     * @param encoding The encoding to use
1216 1212
      */
1217
-    protected void updateCharArrays(final byte limit) {
1218
-        stringConverter = new IRCStringConverter(limit);
1213
+    protected void setEncoding(final IRCEncoding encoding) {
1214
+        stringConverter = new IRCStringConverter(encoding);
1219 1215
     }
1220 1216
 
1221 1217
     /**

+ 39
- 32
src/com/dmdirc/parser/irc/IRCStringConverter.java Bestand weergeven

@@ -19,49 +19,40 @@
19 19
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 20
  * SOFTWARE.
21 21
  */
22
-
23 22
 package com.dmdirc.parser.irc;
24 23
 
25 24
 import com.dmdirc.parser.interfaces.StringConverter;
26 25
 
27 26
 /**
28 27
  * IRC String Converter.
29
- *
30
- * @author Shane Mc Cormack
31 28
  */
32 29
 public class IRCStringConverter implements StringConverter {
33 30
 
34
-    /** Characters to use when converting tolowercase. */
31
+    /** Characters to use when converting to lowercase. */
35 32
     private final char[] lowercase;
36
-    /** Characters to use when converting touppercase. */
33
+    /** Characters to use when converting to uppercase. */
37 34
     private final char[] uppercase;
38
-    /** limit. */
39
-    private final byte limit;
35
+    /** Encoding to use. */
36
+    private final IRCEncoding encoding;
40 37
 
41 38
     /**
42 39
      * Create a new IRCStringConverter with rfc1459 encoding.
43 40
      */
44 41
     public IRCStringConverter() {
45
-        this((byte) 4);
42
+        this(IRCEncoding.RFC1459);
46 43
     }
47 44
 
48 45
     /**
49 46
      * Create a new IRCStringConverter.
50
-     * @param limit Number of post-alphabetical characters to convert
51
-     *              0 = ascii encoding
52
-     *              3 = strict-rfc1459 encoding
53
-     *              4 = rfc1459 encoding
47
+     *
48
+     * @param encoding The encoding to use.
54 49
      */
55
-    public IRCStringConverter(final byte limit) {
56
-        // If limit is out side the boundries, use rfc1459
57
-        if (limit > 4 || limit < 0) {
58
-            this.limit = (byte) 4;
59
-        } else {
60
-            this.limit = limit;
61
-        }
50
+    public IRCStringConverter(final IRCEncoding encoding) {
51
+        this.encoding = encoding;
62 52
 
63 53
         lowercase = new char[127];
64 54
         uppercase = new char[127];
55
+
65 56
         // Normal Chars
66 57
         for (char i = 0; i < lowercase.length; ++i) {
67 58
             lowercase[i] = i;
@@ -69,23 +60,26 @@ public class IRCStringConverter implements StringConverter {
69 60
         }
70 61
 
71 62
         // Replace the uppercase chars with lowercase
72
-        for (char i = 65; i <= (90 + this.limit); ++i) {
63
+        for (char i = 65; i <= (90 + encoding.getLimit()); ++i) {
73 64
             lowercase[i] = (char) (i + 32);
74 65
             uppercase[i + 32] = i;
75 66
         }
76 67
     }
77 68
 
78 69
     /**
79
-     * Get last used chararray limit.
70
+     * Retrieves the encoding used by this converter.
80 71
      *
81
-     * @return last used chararray limit
72
+     * @return This converter's current encoding
82 73
      */
83
-    protected int getLimit() { return limit; }
74
+    public IRCEncoding getEncoding() {
75
+        return encoding;
76
+    }
84 77
 
85 78
     /** {@inheritDoc} */
86
-        @Override
79
+    @Override
87 80
     public String toLowerCase(final String input) {
88 81
         final char[] result = input.toCharArray();
82
+
89 83
         for (int i = 0; i < input.length(); ++i) {
90 84
             if (result[i] >= 0 && result[i] < lowercase.length) {
91 85
                 result[i] = lowercase[result[i]];
@@ -93,13 +87,15 @@ public class IRCStringConverter implements StringConverter {
93 87
                 result[i] = result[i];
94 88
             }
95 89
         }
90
+
96 91
         return new String(result);
97 92
     }
98 93
 
99 94
     /** {@inheritDoc} */
100
-        @Override
95
+    @Override
101 96
     public String toUpperCase(final String input) {
102 97
         final char[] result = input.toCharArray();
98
+
103 99
         for (int i = 0; i < input.length(); ++i) {
104 100
             if (result[i] >= 0 && result[i] < uppercase.length) {
105 101
                 result[i] = uppercase[result[i]];
@@ -107,29 +103,40 @@ public class IRCStringConverter implements StringConverter {
107 103
                 result[i] = result[i];
108 104
             }
109 105
         }
106
+
110 107
         return new String(result);
111 108
     }
112 109
 
113 110
     /** {@inheritDoc} */
114
-        @Override
111
+    @Override
115 112
     public boolean equalsIgnoreCase(final String first, final String second) {
116
-        if (first == null && second == null) { return true; }
117
-        if (first == null || second == null) { return false; }
118
-        boolean result = (first.length() == second.length());
113
+        if (first == null && second == null) {
114
+            return true;
115
+        }
116
+
117
+        if (first == null || second == null) {
118
+            return false;
119
+        }
120
+
121
+        boolean result = first.length() == second.length();
122
+
119 123
         if (result) {
120 124
             final char[] firstChar = first.toCharArray();
121 125
             final char[] secondChar = second.toCharArray();
126
+
122 127
             for (int i = 0; i < first.length(); ++i) {
123 128
                 if (firstChar[i] < lowercase.length && secondChar[i] < lowercase.length) {
124
-                    result = (lowercase[firstChar[i]] == lowercase[secondChar[i]]);
129
+                    result = lowercase[firstChar[i]] == lowercase[secondChar[i]];
125 130
                 } else {
126 131
                     result = firstChar[i] == secondChar[i];
127 132
                 }
128
-                if (!result) { break; }
133
+
134
+                if (!result) {
135
+                    break;
136
+                }
129 137
             }
130 138
         }
131 139
 
132 140
         return result;
133 141
     }
134
-
135 142
 }

+ 61
- 39
src/com/dmdirc/parser/irc/Process004005.java Bestand weergeven

@@ -32,6 +32,7 @@ import java.util.regex.Pattern;
32 32
  * Process ISUPPORT lines.
33 33
  */
34 34
 public class Process004005 extends IRCProcessor {
35
+
35 36
     /**
36 37
      * Process ISUPPORT lines.
37 38
      *
@@ -40,80 +41,99 @@ public class Process004005 extends IRCProcessor {
40 41
      */
41 42
     @Override
42 43
     public void process(final String sParam, final String[] token) {
43
-        if (sParam.equals("002")) {
44
+        if ("002".equals(sParam)) {
44 45
             final Pattern pattern = Pattern.compile("running(?: version)? (.*)$");
45 46
             final Matcher matcher = pattern.matcher(myParser.getLastLine());
46 47
             if (matcher.find()) {
47 48
                 myParser.h005Info.put("002IRCD", matcher.group(1));
48 49
             }
49
-        } else if (sParam.equals("003")) {
50
+        } else if ("003".equals(sParam)) {
50 51
             myParser.h005Info.put("003IRCD", token[token.length - 1]);
51
-        } else if (sParam.equals("004")) {
52
+        } else if ("004".equals(sParam)) {
52 53
             // 004
53 54
             final boolean multiParam = token.length > 4;
54 55
             int i = multiParam ? 4 : 1;
55 56
             final String[] bits = multiParam ? token : token[3].split(" ");
56 57
 
57 58
             myParser.h005Info.put("004IRCD", bits[i++]);
58
-            // some IRCDs put a timestamp where the usermodes should be
59
-            // (issues 4140. 4181 and 4183) so check to see if this is numeric
60
-            // only, and if so, skip it.
61
-            if (bits[i].matches("^\\d+$")) { i++; }
59
+
60
+            if (bits[i].matches("^\\d+$")) {
61
+                // some IRCDs put a timestamp where the usermodes should be
62
+                // (issues 4140. 4181 and 4183) so check to see if this is
63
+                // numeric only, and if so, skip it.
64
+                i++;
65
+            }
66
+
62 67
             myParser.h005Info.put("USERMODES", bits[i++]);
63 68
             myParser.h005Info.put("USERCHANMODES", bits[i++]);
64
-            if (bits.length > i) { myParser.h005Info.put("USERCHANPARAMMODES", bits[i++]); } // INSPIRCD includes an extra param
69
+
70
+            if (bits.length > i) {
71
+                // INSPIRCD includes an extra param
72
+                myParser.h005Info.put("USERCHANPARAMMODES", bits[i++]);
73
+            }
74
+
65 75
             myParser.parseUserModes();
66
-        } else if (sParam.equals("005")) {
67
-            // 005
76
+        } else if ("005".equals(sParam)) {
68 77
             for (int i = 3; i < token.length; i++) {
69 78
                 final String[] bits = token[i].split("=", 2);
70
-                if (bits[0].isEmpty()) { continue; }
71
-                final boolean isNegation = (bits[0].charAt(0) == '-');
72
-                final String sKey = (isNegation) ? bits[0].substring(1).toUpperCase() : bits[0].toUpperCase();
73
-                final String sValue = (bits.length == 2) ? bits[1] : "";
74
-                callDebugInfo(IRCParser.DEBUG_INFO, "%s => %s", sKey, sValue);
79
+
80
+                if (bits[0].isEmpty()) {
81
+                    continue;
82
+                }
83
+
84
+                final boolean isNegation = bits[0].charAt(0) == '-';
85
+                final String key = (isNegation ? bits[0].substring(1) : bits[0]).toUpperCase();
86
+                final String value = bits.length == 2 ? bits[1] : "";
87
+
88
+                callDebugInfo(IRCParser.DEBUG_INFO, "%s => %s", key, value);
89
+
75 90
                 if (isNegation) {
76
-                    myParser.h005Info.remove(sKey);
91
+                    myParser.h005Info.remove(key);
77 92
                 } else {
78
-                    myParser.h005Info.put(sKey, sValue);
93
+                    myParser.h005Info.put(key, value);
79 94
                 }
80
-                if (sKey.equals("NETWORK") && !isNegation) {
81
-                    myParser.networkName = sValue;
95
+
96
+                if ("NETWORK".equals(key) && !isNegation) {
97
+                    myParser.networkName = value;
82 98
                     callGotNetwork();
83
-                } else if (sKey.equals("CASEMAPPING") && !isNegation) {
84
-                    byte limit = (byte) 4;
85
-                    if (sValue.equalsIgnoreCase("strict-rfc1459")) {
86
-                        limit = (byte) 3;
87
-                    } else if (sValue.equalsIgnoreCase("ascii")) {
88
-                        limit = (byte) 0;
89
-                    } else if (!sValue.equalsIgnoreCase("rfc1459")) {
90
-                        myParser.callErrorInfo(new ParserError(ParserError.ERROR_WARNING, "Unknown casemapping: '" + sValue + "' - assuming rfc1459", myParser.getLastLine()));
99
+                } else if ("CASEMAPPING".equals(key) && !isNegation) {
100
+                    IRCEncoding encoding = IRCEncoding.RFC1459;
101
+
102
+                    try {
103
+                        encoding = IRCEncoding.valueOf(value.toUpperCase().replace('-', '_'));
104
+                    } catch (IllegalArgumentException ex) {
105
+                        myParser.callErrorInfo(new ParserError(
106
+                                ParserError.ERROR_WARNING,
107
+                                "Unknown casemapping: '" + value + "' - assuming rfc1459",
108
+                                myParser.getLastLine()));
91 109
                     }
92
-                    final boolean limitChanged = (myParser.getStringConverter().getLimit() != limit);
93
-                    myParser.updateCharArrays(limit);
94
-                    if (limitChanged && myParser.knownClients() == 1) {
110
+
111
+                    final boolean encodingChanged = myParser.getStringConverter().getEncoding() != encoding;
112
+                    myParser.setEncoding(encoding);
113
+
114
+                    if (encodingChanged && myParser.knownClients() == 1) {
95 115
                         // This means that the casemapping is not rfc1459
96 116
                         // We have only added ourselves so far (from 001)
97 117
                         // We can fix the hashtable easily.
98 118
                         myParser.removeClient(myParser.getLocalClient());
99 119
                         myParser.addClient(myParser.getLocalClient());
100 120
                     }
101
-                } else if (sKey.equals("CHANTYPES")) {
121
+                } else if ("CHANTYPES".equals(key)) {
102 122
                     myParser.parseChanPrefix();
103
-                } else if (sKey.equals("PREFIX")) {
123
+                } else if ("PREFIX".equals(key)) {
104 124
                     myParser.parsePrefixModes();
105
-                } else if (sKey.equals("CHANMODES")) {
125
+                } else if ("CHANMODES".equals(key)) {
106 126
                     myParser.parseChanModes();
107
-                } else if (sKey.equals("NAMESX") || sKey.equals("UHNAMES")) {
108
-                    myParser.sendString("PROTOCTL " + sKey);
109
-                } else if (sKey.equals("LISTMODE")) {
127
+                } else if ("NAMESX".equals(key) || "UHNAMES".equals(key)) {
128
+                    myParser.sendString("PROTOCTL " + key);
129
+                } else if ("LISTMODE".equals(key)) {
110 130
                     // Support for potential future decent mode listing in the protocol
111 131
                     //
112 132
                     // See my proposal: http://shanemcc.co.uk/irc/#listmode
113 133
                     // Add listmode handler
114 134
                     String[] handles = new String[2];
115
-                    handles[0] = sValue; // List mode item
116
-                    final String endValue = "" + (Integer.parseInt(sValue) + 1);
135
+                    handles[0] = value; // List mode item
136
+                    final String endValue = "" + (Integer.parseInt(value) + 1);
117 137
                     myParser.h005Info.put("LISTMODEEND", endValue);
118 138
                     handles[1] = endValue; // List mode end
119 139
                     // Add listmode handlers
@@ -156,6 +176,8 @@ public class Process004005 extends IRCProcessor {
156 176
      * @param parser IRCParser That owns this IRCProcessor
157 177
      * @param manager ProcessingManager that is in charge of this IRCProcessor
158 178
      */
159
-    protected Process004005(final IRCParser parser, final ProcessingManager manager) { super(parser, manager); }
179
+    protected Process004005(final IRCParser parser, final ProcessingManager manager) {
180
+        super(parser, manager);
181
+    }
160 182
 
161 183
 }

+ 8
- 15
test/com/dmdirc/parser/irc/IRCStringConverterTest.java Bestand weergeven

@@ -29,13 +29,13 @@ public class IRCStringConverterTest {
29 29
     @Test
30 30
     public void testCaseConversion() {
31 31
         final IRCParser asciiParser = new IRCParser();
32
-        asciiParser.updateCharArrays((byte) 0);
32
+        asciiParser.setEncoding(IRCEncoding.ASCII);
33 33
 
34 34
         final IRCParser rfcParser = new IRCParser();
35
-        rfcParser.updateCharArrays((byte) 4);
35
+        rfcParser.setEncoding(IRCEncoding.RFC1459);
36 36
 
37 37
         final IRCParser strictParser = new IRCParser();
38
-        strictParser.updateCharArrays((byte) 3);
38
+        strictParser.setEncoding(IRCEncoding.STRICT_RFC1459);
39 39
 
40 40
         final String[][] testcases = {
41 41
             {"12345", "12345", "12345", "12345"},
@@ -66,28 +66,21 @@ public class IRCStringConverterTest {
66 66
             assertEquals(testcase[0], strictU);
67 67
         }
68 68
     }
69
-    
70
-    @Test
71
-    public void testLimit() {
72
-        final IRCStringConverter ircsc = new IRCStringConverter((byte) 100);
73
-        
74
-        assertEquals(4, ircsc.getLimit());
75
-    }
76 69
 
77 70
     @Test
78 71
     public void testDefaultLimit() {
79 72
         final IRCStringConverter ircsc = new IRCStringConverter();
80 73
 
81
-        assertEquals(4, ircsc.getLimit());
74
+        assertEquals(IRCEncoding.RFC1459, ircsc.getEncoding());
82 75
     }
83
-    
76
+
84 77
     @Test
85 78
     public void testEqualsNull() {
86
-        final IRCStringConverter ircsc = new IRCStringConverter((byte) 100);
87
-        
79
+        final IRCStringConverter ircsc = new IRCStringConverter(IRCEncoding.ASCII);
80
+
88 81
         assertTrue(ircsc.equalsIgnoreCase(null, null));
89 82
         assertFalse(ircsc.equalsIgnoreCase("null", null));
90 83
         assertFalse(ircsc.equalsIgnoreCase(null, "null"));
91
-    }    
84
+    }
92 85
 
93 86
 }

+ 19
- 19
test/com/dmdirc/parser/irc/Process004005Test.java Bestand weergeven

@@ -31,45 +31,45 @@ import static org.junit.Assert.*;
31 31
 import static org.mockito.Mockito.*;
32 32
 
33 33
 public class Process004005Test {
34
-    
35
-    private TestParser doCaseMappingTest(final String target, final int expected) {
34
+
35
+    private TestParser doCaseMappingTest(final String target, final IRCEncoding expected) {
36 36
         final TestParser parser = new TestParser();
37 37
         parser.injectConnectionStrings();
38 38
         parser.injectLine(":server 005 nick CASEMAPPING=" + target
39 39
                     + " :are supported by this server");
40
-        
41
-        assertEquals(expected, parser.getStringConverter().getLimit());
42
-        
40
+
41
+        assertEquals(expected, parser.getStringConverter().getEncoding());
42
+
43 43
         return parser;
44 44
     }
45
-    
45
+
46 46
     @Test
47 47
     public void testCaseMappingASCII() {
48
-        doCaseMappingTest("ascii", 0);
49
-        doCaseMappingTest("ASCII", 0);
48
+        doCaseMappingTest("ascii", IRCEncoding.ASCII);
49
+        doCaseMappingTest("ASCII", IRCEncoding.ASCII);
50 50
     }
51
-    
51
+
52 52
     @Test
53 53
     public void testCaseMappingRFC() {
54
-        doCaseMappingTest("rfc1459", 4);
55
-        doCaseMappingTest("RFC1459", 4);
54
+        doCaseMappingTest("rfc1459", IRCEncoding.RFC1459);
55
+        doCaseMappingTest("RFC1459", IRCEncoding.RFC1459);
56 56
     }
57
-    
57
+
58 58
     @Test
59 59
     public void testCaseMappingStrict() {
60
-        doCaseMappingTest("strict-rfc1459", 3);
61
-        doCaseMappingTest("strict-RFC1459", 3);        
60
+        doCaseMappingTest("strict-rfc1459", IRCEncoding.STRICT_RFC1459);
61
+        doCaseMappingTest("strict-RFC1459", IRCEncoding.STRICT_RFC1459);
62 62
     }
63
-    
63
+
64 64
     @Test
65 65
     public void testCaseMappingUnknown() {
66
-        final TestParser tp = doCaseMappingTest("rfc1459", 4);
66
+        final TestParser tp = doCaseMappingTest("rfc1459", IRCEncoding.RFC1459);
67 67
         final ErrorInfoListener info = mock(ErrorInfoListener.class);
68
-        
68
+
69 69
         tp.getCallbackManager().addCallback(ErrorInfoListener.class, info);
70
-        
70
+
71 71
         tp.injectLine(":server 005 nick CASEMAPPING=unknown :are supported by this server");
72
-        
72
+
73 73
         verify(info).onErrorInfo(same(tp), (Date) anyObject(), (ParserError) anyObject());
74 74
     }
75 75
 

Laden…
Annuleren
Opslaan