diff options
author | Ben Harris <ben@tilde.team> | 2020-04-22 16:28:51 -0400 |
---|---|---|
committer | Ben Harris <ben@tilde.team> | 2020-04-22 16:28:51 -0400 |
commit | 933a4f85604e21445c9bac8272d64cf3e6f65e00 (patch) | |
tree | 5b300ca37beff5cf11ed67a8b6e3550d24cf18a3 | |
parent | 338763fde71ba2dc0de8ea5e2437d24ee365874b (diff) |
rename to IrcSharp
also tidy up formatting with vs tools
-rw-r--r-- | .editorconfig | 57 | ||||
-rw-r--r-- | IrcSharp.sln (renamed from IrcTokens.sln) | 19 | ||||
-rw-r--r-- | IrcStates/Casemap.cs | 43 | ||||
-rw-r--r-- | IrcStates/Channel.cs | 69 | ||||
-rw-r--r-- | IrcStates/Emit.cs | 6 | ||||
-rw-r--r-- | IrcStates/ISupport.cs | 7 | ||||
-rw-r--r-- | IrcStates/IrcStates.csproj | 21 | ||||
-rw-r--r-- | IrcStates/Numeric.cs | 49 | ||||
-rw-r--r-- | IrcStates/Server.cs | 6 | ||||
-rw-r--r-- | IrcStates/Tests/Cap.cs | 9 | ||||
-rw-r--r-- | IrcStates/Tests/Casemap.cs | 9 | ||||
-rw-r--r-- | IrcStates/Tests/Channel.cs | 9 | ||||
-rw-r--r-- | IrcStates/Tests/Emit.cs | 9 | ||||
-rw-r--r-- | IrcStates/Tests/ISupport.cs | 10 | ||||
-rw-r--r-- | IrcStates/Tests/Mode.cs | 9 | ||||
-rw-r--r-- | IrcStates/Tests/Motd.cs | 9 | ||||
-rw-r--r-- | IrcStates/Tests/User.cs | 9 | ||||
-rw-r--r-- | IrcStates/Tests/Who.cs | 9 | ||||
-rw-r--r-- | IrcStates/User.cs | 28 | ||||
-rw-r--r-- | IrcTokens/Hostmask.cs | 30 | ||||
-rw-r--r-- | IrcTokens/Line.cs | 47 | ||||
-rw-r--r-- | IrcTokens/Protocol.cs | 2 | ||||
-rw-r--r-- | IrcTokens/StatefulDecoder.cs | 8 | ||||
-rw-r--r-- | IrcTokens/StatefulEncoder.cs | 4 | ||||
-rw-r--r-- | IrcTokens/Tests/Format.cs (renamed from IrcTokens/Tests/FormatTests.cs) | 36 | ||||
-rw-r--r-- | IrcTokens/Tests/Hostmask.cs (renamed from IrcTokens/Tests/HostmaskTests.cs) | 12 | ||||
-rw-r--r-- | IrcTokens/Tests/Parser.cs (renamed from IrcTokens/Tests/ParserTests.cs) | 10 | ||||
-rw-r--r-- | IrcTokens/Tests/StatefulDecoder.cs (renamed from IrcTokens/Tests/StatefulDecoderTests.cs) | 17 | ||||
-rw-r--r-- | IrcTokens/Tests/StatefulEncoder.cs (renamed from IrcTokens/Tests/StatefulEncoderTests.cs) | 11 | ||||
-rw-r--r-- | IrcTokens/Tests/Tokenization.cs (renamed from IrcTokens/Tests/TokenizationTests.cs) | 14 | ||||
-rw-r--r-- | Sample/Client.cs | 19 | ||||
-rw-r--r-- | Sample/Program.cs | 8 | ||||
-rw-r--r-- | Sample/TokensSample.csproj (renamed from Sample/Sample.csproj) | 0 | ||||
-rw-r--r-- | StatesSample/Program.cs | 12 | ||||
-rw-r--r-- | StatesSample/StatesSample.csproj | 12 |
35 files changed, 548 insertions, 81 deletions
diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c81e008 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,57 @@ + +[*.proto] +indent_style=tab +indent_size=tab +tab_width=4 + +[*.{asax,ascx,aspx,cs,cshtml,css,htm,html,js,jsx,master,razor,skin,ts,tsx,vb,xaml,xamlx,xoml}] +indent_style=space +indent_size=4 +tab_width=4 + +[*.{appxmanifest,axml,build,config,csproj,dbml,discomap,dtd,json,jsproj,lsproj,njsproj,nuspec,proj,props,resjson,resw,resx,StyleCop,targets,tasks,vbproj,xml,xsd}] +indent_style=space +indent_size=2 +tab_width=2 + +[*] + +# Microsoft .NET properties +csharp_new_line_before_members_in_object_initializers=true +csharp_preferred_modifier_order=public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion +csharp_style_var_elsewhere=true:suggestion +csharp_style_var_for_built_in_types=true:suggestion +csharp_style_var_when_type_is_apparent=true:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators=never_if_unnecessary:none +dotnet_style_parentheses_in_other_binary_operators=never_if_unnecessary:none +dotnet_style_parentheses_in_relational_binary_operators=never_if_unnecessary:none +dotnet_style_predefined_type_for_locals_parameters_members=true:suggestion +dotnet_style_predefined_type_for_member_access=true:suggestion +dotnet_style_qualification_for_event=false:suggestion +dotnet_style_qualification_for_field=false:suggestion +dotnet_style_qualification_for_method=false:suggestion +dotnet_style_qualification_for_property=false:suggestion +dotnet_style_require_accessibility_modifiers=for_non_interface_members:suggestion + +# ReSharper inspection severities +resharper_arrange_redundant_parentheses_highlighting=hint +resharper_arrange_this_qualifier_highlighting=hint +resharper_arrange_type_member_modifiers_highlighting=hint +resharper_arrange_type_modifiers_highlighting=hint +resharper_built_in_type_reference_style_for_member_access_highlighting=hint +resharper_built_in_type_reference_style_highlighting=hint +resharper_redundant_base_qualifier_highlighting=warning +resharper_suggest_var_or_type_built_in_types_highlighting=hint +resharper_suggest_var_or_type_elsewhere_highlighting=hint +resharper_suggest_var_or_type_simple_types_highlighting=hint + +# ReSharper properties +resharper_csharp_insert_final_newline=true +resharper_int_align_assignments=true +resharper_int_align_switch_expressions=true +resharper_int_align_switch_sections=true +resharper_int_align_variables=true +resharper_keep_existing_embedded_arrangement=false +resharper_keep_existing_switch_expression_arrangement=false +resharper_place_simple_case_statement_on_same_line=if_owner_is_single_line +resharper_xmldoc_max_blank_lines_between_tags=1 diff --git a/IrcTokens.sln b/IrcSharp.sln index c9b3d28..030a2af 100644 --- a/IrcTokens.sln +++ b/IrcSharp.sln @@ -5,7 +5,16 @@ VisualStudioVersion = 16.0.30011.22 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IrcTokens", "IrcTokens\IrcTokens.csproj", "{9E812F45-B2CD-42D2-8378-EBEBF8697905}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample", "Sample\Sample.csproj", "{A45DA39B-6B47-4713-8049-3B36E0235B67}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TokensSample", "Sample\TokensSample.csproj", "{A45DA39B-6B47-4713-8049-3B36E0235B67}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IrcStates", "IrcStates\IrcStates.csproj", "{233E3CB4-61F1-4368-9139-7E9F4A58ED2D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatesSample", "StatesSample\StatesSample.csproj", "{BC9F6696-9D83-4F7A-9E15-CE4D3626C1AF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1A85EB22-D7B4-417F-AC3B-DAFD97DDEA08}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +30,14 @@ Global {A45DA39B-6B47-4713-8049-3B36E0235B67}.Debug|Any CPU.Build.0 = Debug|Any CPU {A45DA39B-6B47-4713-8049-3B36E0235B67}.Release|Any CPU.ActiveCfg = Release|Any CPU {A45DA39B-6B47-4713-8049-3B36E0235B67}.Release|Any CPU.Build.0 = Release|Any CPU + {233E3CB4-61F1-4368-9139-7E9F4A58ED2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {233E3CB4-61F1-4368-9139-7E9F4A58ED2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {233E3CB4-61F1-4368-9139-7E9F4A58ED2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {233E3CB4-61F1-4368-9139-7E9F4A58ED2D}.Release|Any CPU.Build.0 = Release|Any CPU + {BC9F6696-9D83-4F7A-9E15-CE4D3626C1AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC9F6696-9D83-4F7A-9E15-CE4D3626C1AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC9F6696-9D83-4F7A-9E15-CE4D3626C1AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC9F6696-9D83-4F7A-9E15-CE4D3626C1AF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/IrcStates/Casemap.cs b/IrcStates/Casemap.cs new file mode 100644 index 0000000..484c490 --- /dev/null +++ b/IrcStates/Casemap.cs @@ -0,0 +1,43 @@ +using System; + +namespace IrcStates +{ + public static class Casemap + { + public enum CaseMapping + { + Rfc1459, + Ascii + } + + private const string AsciiUpperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private const string AsciiLowerChars = "abcdefghijklmnopqrstuvwxyz"; + private const string Rfc1459UpperChars = AsciiUpperChars + @"[]~\"; + private const string Rfc1459LowerChars = AsciiLowerChars + @"{}^|"; + + private static string Replace(string s, string upper, string lower) + { + for (var i = 0; i < upper.Length; ++i) + { + s = s.Replace(upper[i], lower[i]); + } + + return s; + } + + public static string CaseFold(CaseMapping mapping, string s) + { + if (s != null) + { + return mapping switch + { + CaseMapping.Rfc1459 => Replace(s, Rfc1459UpperChars, Rfc1459LowerChars), + CaseMapping.Ascii => Replace(s, AsciiUpperChars, AsciiLowerChars), + _ => throw new ArgumentOutOfRangeException(nameof(mapping), mapping, null) + }; + } + + return string.Empty; + } + } +} diff --git a/IrcStates/Channel.cs b/IrcStates/Channel.cs new file mode 100644 index 0000000..1850e51 --- /dev/null +++ b/IrcStates/Channel.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace IrcStates +{ + public class Channel + { + public string Name { get; set; } + public string NameLower { get; set; } + public Dictionary<string, User> Users { get; set; } + public string Topic { get; set; } + public string TopicSetter { get; set; } + public DateTime TopicTime { get; set; } + public DateTime Created { get; set; } + public Dictionary<string, List<string>> ListModes { get; set; } + public Dictionary<string, string> Modes { get; set; } + + public override string ToString() + { + return $"Channel(name={Name})"; + } + + public void SetName(string name, string nameLower) + { + Name = name; + NameLower = nameLower; + } + + public void AddMode(string ch, string param, bool listMode) + { + if (listMode) + { + if (!ListModes.ContainsKey(ch)) + { + ListModes[ch] = new List<string>(); + } + + if (ListModes[ch].Contains(param)) + { + ListModes[ch].Add(param ?? string.Empty); + } + } + else + { + Modes[ch] = param; + } + } + + public void RemoveMode(string ch, string param) + { + if (ListModes.ContainsKey(ch)) + { + if (ListModes[ch].Contains(param)) + { + ListModes[ch].Remove(param); + if (!ListModes[ch].Any()) + { + ListModes.Remove(ch); + } + } + } + else if (Modes.ContainsKey(ch)) + { + Modes.Remove(ch); + } + } + } +} diff --git a/IrcStates/Emit.cs b/IrcStates/Emit.cs new file mode 100644 index 0000000..7fc41ae --- /dev/null +++ b/IrcStates/Emit.cs @@ -0,0 +1,6 @@ +namespace IrcStates +{ + public class Emit + { + } +} diff --git a/IrcStates/ISupport.cs b/IrcStates/ISupport.cs new file mode 100644 index 0000000..91e6d6d --- /dev/null +++ b/IrcStates/ISupport.cs @@ -0,0 +1,7 @@ +// ReSharper disable InconsistentNaming +namespace IrcStates +{ + public class ISupport + { + } +} diff --git a/IrcStates/IrcStates.csproj b/IrcStates/IrcStates.csproj new file mode 100644 index 0000000..7500c8b --- /dev/null +++ b/IrcStates/IrcStates.csproj @@ -0,0 +1,21 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netcoreapp3.1</TargetFramework> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8"> + <PrivateAssets>all</PrivateAssets> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + </PackageReference> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.0" /> + <PackageReference Include="MSTest.TestAdapter" Version="2.1.1" /> + <PackageReference Include="MSTest.TestFramework" Version="2.1.1" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\IrcTokens\IrcTokens.csproj" /> + </ItemGroup> + +</Project> diff --git a/IrcStates/Numeric.cs b/IrcStates/Numeric.cs new file mode 100644 index 0000000..f5525f6 --- /dev/null +++ b/IrcStates/Numeric.cs @@ -0,0 +1,49 @@ +// ReSharper disable InconsistentNaming +namespace IrcStates +{ + public static class Numeric + { + public const string RPL_WELCOME = "001"; + public const string RPL_ISUPPORT = "005"; + public const string RPL_MOTD = "372"; + public const string RPL_MOTDSTART = "375"; + public const string RPL_UMODEIS = "221"; + public const string RPL_VISIBLEHOST = "396"; + + public const string RPL_CHANNELMODEIS = "324"; + public const string RPL_CREATIONTIME = "329"; + public const string RPL_TOPIC = "332"; + public const string RPL_TOPICWHOTIME = "333"; + + public const string RPL_WHOREPLY = "352"; + public const string RPL_WHOSPCRPL = "354"; + public const string RPL_ENDOFWHO = "315"; + public const string RPL_NAMREPLY = "353"; + public const string RPL_ENDOFNAMES = "366"; + + public const string RPL_BANLIST = "367"; + public const string RPL_ENDOFBANLIST = "368"; + public const string RPL_QUIETLIST = "728"; + public const string RPL_ENDOFQUIETLIST = "729"; + + public const string RPL_SASLSUCCESS = "903"; + public const string ERR_SASLFAIL = "904"; + public const string ERR_SASLTOOLONG = "905"; + public const string ERR_SASLABORTED = "906"; + public const string ERR_SASLALREADY = "907"; + public const string RPL_SASLMECHS = "908"; + + public const string RPL_WHOISUSER = "311"; + public const string RPL_WHOISSERVER = "312"; + public const string RPL_WHOISOPERATOR = "313"; + public const string RPL_WHOISIDLE = "317"; + public const string RPL_WHOISCHANNELS = "319"; + public const string RPL_WHOISACCOUNT = "330"; + public const string RPL_WHOISHOST = "378"; + public const string RPL_WHOISMODES = "379"; + public const string RPL_WHOISSECURE = "671"; + public const string RPL_ENDOFWHOIS = "318"; + + public const string ERR_NOSUCHCHANNEL = "403"; + } +} diff --git a/IrcStates/Server.cs b/IrcStates/Server.cs new file mode 100644 index 0000000..9f97f47 --- /dev/null +++ b/IrcStates/Server.cs @@ -0,0 +1,6 @@ +namespace IrcStates +{ + public class Server + { + } +} diff --git a/IrcStates/Tests/Cap.cs b/IrcStates/Tests/Cap.cs new file mode 100644 index 0000000..dcd0e50 --- /dev/null +++ b/IrcStates/Tests/Cap.cs @@ -0,0 +1,9 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IrcStates.Tests +{ + [TestClass] + public class Cap + { + } +} diff --git a/IrcStates/Tests/Casemap.cs b/IrcStates/Tests/Casemap.cs new file mode 100644 index 0000000..fef9a31 --- /dev/null +++ b/IrcStates/Tests/Casemap.cs @@ -0,0 +1,9 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IrcStates.Tests +{ + [TestClass] + public class Casemap + { + } +} diff --git a/IrcStates/Tests/Channel.cs b/IrcStates/Tests/Channel.cs new file mode 100644 index 0000000..0de5f37 --- /dev/null +++ b/IrcStates/Tests/Channel.cs @@ -0,0 +1,9 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IrcStates.Tests +{ + [TestClass] + public class Channel + { + } +} diff --git a/IrcStates/Tests/Emit.cs b/IrcStates/Tests/Emit.cs new file mode 100644 index 0000000..f4495c5 --- /dev/null +++ b/IrcStates/Tests/Emit.cs @@ -0,0 +1,9 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IrcStates.Tests +{ + [TestClass] + public class Emit + { + } +} diff --git a/IrcStates/Tests/ISupport.cs b/IrcStates/Tests/ISupport.cs new file mode 100644 index 0000000..aa6260a --- /dev/null +++ b/IrcStates/Tests/ISupport.cs @@ -0,0 +1,10 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +// ReSharper disable InconsistentNaming + +namespace IrcStates.Tests +{ + [TestClass] + public class ISupport + { + } +} diff --git a/IrcStates/Tests/Mode.cs b/IrcStates/Tests/Mode.cs new file mode 100644 index 0000000..e7b70f4 --- /dev/null +++ b/IrcStates/Tests/Mode.cs @@ -0,0 +1,9 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IrcStates.Tests +{ + [TestClass] + public class Mode + { + } +} diff --git a/IrcStates/Tests/Motd.cs b/IrcStates/Tests/Motd.cs new file mode 100644 index 0000000..8ca7f07 --- /dev/null +++ b/IrcStates/Tests/Motd.cs @@ -0,0 +1,9 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IrcStates.Tests +{ + [TestClass] + public class Motd + { + } +} diff --git a/IrcStates/Tests/User.cs b/IrcStates/Tests/User.cs new file mode 100644 index 0000000..540d31f --- /dev/null +++ b/IrcStates/Tests/User.cs @@ -0,0 +1,9 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IrcStates.Tests +{ + [TestClass] + public class User + { + } +} diff --git a/IrcStates/Tests/Who.cs b/IrcStates/Tests/Who.cs new file mode 100644 index 0000000..359991c --- /dev/null +++ b/IrcStates/Tests/Who.cs @@ -0,0 +1,9 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IrcStates.Tests +{ + [TestClass] + public class Who + { + } +} diff --git a/IrcStates/User.cs b/IrcStates/User.cs new file mode 100644 index 0000000..9bc5ce8 --- /dev/null +++ b/IrcStates/User.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace IrcStates +{ + public class User + { + private string NickName; + private string NickNameLower; + + public string UserName { get; set; } + public string HostName { get; set; } + public string RealName { get; set; } + public string Account { get; set; } + public string Away { get; set; } + public HashSet<string> Channels { get; set; } + + public override string ToString() + { + return $"User(nickname={NickName})"; + } + + public void SetNickName(string nick, string nickLower) + { + NickName = nick; + NickNameLower = nickLower; + } + } +} diff --git a/IrcTokens/Hostmask.cs b/IrcTokens/Hostmask.cs index 0b07f80..01fe7d5 100644 --- a/IrcTokens/Hostmask.cs +++ b/IrcTokens/Hostmask.cs @@ -5,29 +5,45 @@ namespace IrcTokens /// <summary> /// Represents the three parts of a hostmask. Parse with the constructor. /// </summary> - public class Hostmask + public class Hostmask : IEquatable<Hostmask> { public string NickName { get; set; } public string UserName { get; set; } public string HostName { get; set; } - public override string ToString() => _source; + public override string ToString() + { + return _source; + } - public override int GetHashCode() => _source.GetHashCode(StringComparison.Ordinal); + public override int GetHashCode() + { + return _source.GetHashCode(StringComparison.Ordinal); + } - public override bool Equals(object obj) + public bool Equals(Hostmask other) { - if (obj == null || GetType() != obj.GetType()) + if (other == null) + { return false; + } - return _source == ((Hostmask) obj)._source; + return _source == other._source; + } + + public override bool Equals(object obj) + { + return Equals(obj as Hostmask); } private readonly string _source; public Hostmask(string source) { - if (source == null) return; + if (source == null) + { + return; + } _source = source; diff --git a/IrcTokens/Line.cs b/IrcTokens/Line.cs index 9056097..24efe4a 100644 --- a/IrcTokens/Line.cs +++ b/IrcTokens/Line.cs @@ -8,7 +8,7 @@ namespace IrcTokens /// <summary> /// Tools to represent, parse, and format IRC lines /// </summary> - public class Line + public class Line : IEquatable<Line> { public Dictionary<string, string> Tags { get; set; } public string Source { get; set; } @@ -16,32 +16,52 @@ namespace IrcTokens public List<string> Params { get; set; } private Hostmask _hostmask; - private readonly string _rawLine; public override string ToString() { var vars = new List<string>(); if (Command != null) + { vars.Add($"command={Command}"); + } + if (Source != null) + { vars.Add($"source={Source}"); + } + if (Params != null && Params.Any()) + { vars.Add($"params=[{string.Join(",", Params)}]"); + } + if (Tags != null && Tags.Any()) + { vars.Add($"tags=[{string.Join(";", Tags.Select(kvp => $"{kvp.Key}={kvp.Value}"))}]"); + } return $"Line({string.Join(", ", vars)})"; } - public override int GetHashCode() => Format().GetHashCode(StringComparison.Ordinal); + public override int GetHashCode() + { + return Format().GetHashCode(StringComparison.Ordinal); + } - public override bool Equals(object obj) + public bool Equals(Line other) { - if (obj == null || GetType() != obj.GetType()) + if (other == null) + { return false; + } - return Format() == ((Line) obj).Format(); + return Format() == other.Format(); + } + + public override bool Equals(object obj) + { + return Equals(obj as Line); } public Hostmask Hostmask => @@ -56,9 +76,10 @@ namespace IrcTokens public Line(string line) { if (string.IsNullOrWhiteSpace(line)) + { throw new ArgumentNullException(nameof(line)); + } - _rawLine = line; string[] split; if (line.StartsWith('@')) @@ -97,7 +118,7 @@ namespace IrcTokens Params = line.Contains(' ', StringComparison.Ordinal) ? line.Split(' ', StringSplitOptions.RemoveEmptyEntries).ToList() - : new List<string> {line}; + : new List<string> { line }; if (Params[0].StartsWith(':')) { @@ -135,7 +156,9 @@ namespace IrcTokens } if (Source != null) + { outs.Add($":{Source}"); + } outs.Add(Command); @@ -147,14 +170,22 @@ namespace IrcTokens foreach (var p in Params) { if (p.Contains(' ', StringComparison.Ordinal)) + { throw new ArgumentException(@"non-last parameters cannot have spaces", p); + } + if (p.StartsWith(':')) + { throw new ArgumentException(@"non-last parameters cannot start with colon", p); + } } outs.AddRange(Params); if (string.IsNullOrWhiteSpace(last) || last.Contains(' ', StringComparison.Ordinal) || last.StartsWith(':')) + { last = $":{last}"; + } + outs.Add(last); } diff --git a/IrcTokens/Protocol.cs b/IrcTokens/Protocol.cs index 3769ea3..6ddb079 100644 --- a/IrcTokens/Protocol.cs +++ b/IrcTokens/Protocol.cs @@ -50,7 +50,9 @@ namespace IrcTokens } } else + { unescaped.Append(current); + } } return unescaped.ToString(); diff --git a/IrcTokens/StatefulDecoder.cs b/IrcTokens/StatefulDecoder.cs index 2304431..47106d9 100644 --- a/IrcTokens/StatefulDecoder.cs +++ b/IrcTokens/StatefulDecoder.cs @@ -18,8 +18,10 @@ namespace IrcTokens set { if (value != null) + { _encoding = Encoding.GetEncoding(value.CodePage, EncoderFallback.ExceptionFallback, DecoderFallback.ReplacementFallback); + } } } @@ -30,8 +32,10 @@ namespace IrcTokens set { if (value != null) - _encoding = Encoding.GetEncoding(value.CodePage, EncoderFallback.ReplacementFallback, + { + _fallback = Encoding.GetEncoding(value.CodePage, EncoderFallback.ReplacementFallback, DecoderFallback.ReplacementFallback); + } } } @@ -55,7 +59,9 @@ namespace IrcTokens public List<Line> Push(byte[] data) { if (data == null || data.Length == 0) + { return null; + } _buffer = _buffer.Concat(data).ToArray(); diff --git a/IrcTokens/StatefulEncoder.cs b/IrcTokens/StatefulEncoder.cs index 17295eb..c036400 100644 --- a/IrcTokens/StatefulEncoder.cs +++ b/IrcTokens/StatefulEncoder.cs @@ -16,8 +16,10 @@ namespace IrcTokens set { if (value != null) + { _encoding = Encoding.GetEncoding(value.CodePage, EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback); + } } } @@ -52,7 +54,9 @@ namespace IrcTokens public void Push(Line line) { if (line == null) + { throw new ArgumentNullException(nameof(line)); + } PendingBytes = PendingBytes.Concat(Encoding.GetBytes($"{line.Format()}\r\n")).ToArray(); _bufferedLines.Enqueue(line); diff --git a/IrcTokens/Tests/FormatTests.cs b/IrcTokens/Tests/Format.cs index a804c1d..64f974a 100644 --- a/IrcTokens/Tests/FormatTests.cs +++ b/IrcTokens/Tests/Format.cs @@ -5,16 +5,16 @@ using System.Collections.Generic; namespace IrcTokens.Tests { [TestClass] - public class FormatTests + public class Format { [TestMethod] public void TestTags() { var line = new Line { - Command = "PRIVMSG", - Params = new List<string> {"#channel", "hello"}, - Tags = new Dictionary<string, string> {{"id", "\\" + " " + ";" + "\r\n"}} + Command = "PRIVMSG", + Params = new List<string> { "#channel", "hello" }, + Tags = new Dictionary<string, string> { { "id", "\\" + " " + ";" + "\r\n" } } }.Format(); Assert.AreEqual("@id=\\\\\\s\\:\\r\\n PRIVMSG #channel hello", line); @@ -25,8 +25,8 @@ namespace IrcTokens.Tests { var line = new Line { - Command = "PRIVMSG", - Params = new List<string> {"#channel", "hello"} + Command = "PRIVMSG", + Params = new List<string> { "#channel", "hello" } }.Format(); Assert.AreEqual("PRIVMSG #channel hello", line); @@ -38,8 +38,8 @@ namespace IrcTokens.Tests var line = new Line { Command = "PRIVMSG", - Params = new List<string> {"#channel", "hello"}, - Tags = new Dictionary<string, string> {{"a", null}} + Params = new List<string> { "#channel", "hello" }, + Tags = new Dictionary<string, string> { { "a", null } } }.Format(); Assert.AreEqual("@a PRIVMSG #channel hello", line); @@ -51,8 +51,8 @@ namespace IrcTokens.Tests var line = new Line { Command = "PRIVMSG", - Params = new List<string> {"#channel", "hello"}, - Tags = new Dictionary<string, string> {{"a", ""}} + Params = new List<string> { "#channel", "hello" }, + Tags = new Dictionary<string, string> { { "a", "" } } }.Format(); Assert.AreEqual("@a PRIVMSG #channel hello", line); @@ -64,7 +64,7 @@ namespace IrcTokens.Tests var line = new Line { Command = "PRIVMSG", - Params = new List<string> {"#channel", "hello"}, + Params = new List<string> { "#channel", "hello" }, Source = "nick!user@host" }.Format(); @@ -74,14 +74,14 @@ namespace IrcTokens.Tests [TestMethod] public void TestCommandLowercase() { - var line = new Line {Command = "privmsg"}.Format(); + var line = new Line { Command = "privmsg" }.Format(); Assert.AreEqual("privmsg", line); } [TestMethod] public void TestCommandUppercase() { - var line = new Line {Command = "PRIVMSG"}.Format(); + var line = new Line { Command = "PRIVMSG" }.Format(); Assert.AreEqual("PRIVMSG", line); } @@ -91,7 +91,7 @@ namespace IrcTokens.Tests var line = new Line { Command = "PRIVMSG", - Params = new List<string> {"#channel", "hello world"} + Params = new List<string> { "#channel", "hello world" } }.Format(); Assert.AreEqual("PRIVMSG #channel :hello world", line); @@ -103,7 +103,7 @@ namespace IrcTokens.Tests var line = new Line { Command = "PRIVMSG", - Params = new List<string> {"#channel", "helloworld"} + Params = new List<string> { "#channel", "helloworld" } }.Format(); Assert.AreEqual("PRIVMSG #channel helloworld", line); @@ -115,7 +115,7 @@ namespace IrcTokens.Tests var line = new Line { Command = "PRIVMSG", - Params = new List<string> {"#channel", ":helloworld"} + Params = new List<string> { "#channel", ":helloworld" } }.Format(); Assert.AreEqual("PRIVMSG #channel ::helloworld", line); @@ -129,7 +129,7 @@ namespace IrcTokens.Tests new Line { Command = "USER", - Params = new List<string> {"user", "0 *", "real name"} + Params = new List<string> { "user", "0 *", "real name" } }.Format(); }); } @@ -142,7 +142,7 @@ namespace IrcTokens.Tests new Line { Command = "PRIVMSG", - Params = new List<string> {":#channel", "hello"} + Params = new List<string> { ":#channel", "hello" } }.Format(); }); } diff --git a/IrcTokens/Tests/HostmaskTests.cs b/IrcTokens/Tests/Hostmask.cs index 78b8a54..51bc182 100644 --- a/IrcTokens/Tests/HostmaskTests.cs +++ b/IrcTokens/Tests/Hostmask.cs @@ -3,12 +3,12 @@ namespace IrcTokens.Tests { [TestClass] - public class HostmaskTests + public class Hostmask { [TestMethod] public void TestHostmask() { - var hostmask = new Hostmask("nick!user@host"); + var hostmask = new IrcTokens.Hostmask("nick!user@host"); Assert.AreEqual("nick", hostmask.NickName); Assert.AreEqual("user", hostmask.UserName); Assert.AreEqual("host", hostmask.HostName); @@ -17,7 +17,7 @@ namespace IrcTokens.Tests [TestMethod] public void TestNoHostName() { - var hostmask = new Hostmask("nick!user"); + var hostmask = new IrcTokens.Hostmask("nick!user"); Assert.AreEqual("nick", hostmask.NickName); Assert.AreEqual("user", hostmask.UserName); Assert.IsNull(hostmask.HostName); @@ -26,7 +26,7 @@ namespace IrcTokens.Tests [TestMethod] public void TestNoUserName() { - var hostmask = new Hostmask("nick@host"); + var hostmask = new IrcTokens.Hostmask("nick@host"); Assert.AreEqual("nick", hostmask.NickName); Assert.IsNull(hostmask.UserName); Assert.AreEqual("host", hostmask.HostName); @@ -35,7 +35,7 @@ namespace IrcTokens.Tests [TestMethod] public void TestOnlyNickName() { - var hostmask = new Hostmask("nick"); + var hostmask = new IrcTokens.Hostmask("nick"); Assert.AreEqual("nick", hostmask.NickName); Assert.IsNull(hostmask.UserName); Assert.IsNull(hostmask.HostName); @@ -45,7 +45,7 @@ namespace IrcTokens.Tests public void TestHostmaskFromLine() { var line = new Line(":nick!user@host PRIVMSG #channel hello"); - var hostmask = new Hostmask("nick!user@host"); + var hostmask = new IrcTokens.Hostmask("nick!user@host"); Assert.AreEqual(hostmask.ToString(), line.Hostmask.ToString()); Assert.AreEqual("nick", line.Hostmask.NickName); Assert.AreEqual("user", line.Hostmask.UserName); diff --git a/IrcTokens/Tests/ParserTests.cs b/IrcTokens/Tests/Parser.cs index ad734cf..df70b92 100644 --- a/IrcTokens/Tests/ParserTests.cs +++ b/IrcTokens/Tests/Parser.cs @@ -1,15 +1,15 @@ -using System.Collections.Generic; +using IrcTokens.Tests.Data; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Collections.Generic; using System.Globalization; using System.IO; -using IrcTokens.Tests.Data; -using Microsoft.VisualStudio.TestTools.UnitTesting; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; namespace IrcTokens.Tests { [TestClass] - public class ParserTests + public class Parser { private static T LoadYaml<T>(string path) { @@ -46,7 +46,7 @@ namespace IrcTokens.Tests { Command = atoms.Verb, Params = atoms.Params, - Source = atoms.Source ?? null, + Source = atoms.Source, Tags = atoms.Tags }.Format(); diff --git a/IrcTokens/Tests/StatefulDecoderTests.cs b/IrcTokens/Tests/StatefulDecoder.cs index 3e6a078..209a6cf 100644 --- a/IrcTokens/Tests/StatefulDecoderTests.cs +++ b/IrcTokens/Tests/StatefulDecoder.cs @@ -1,19 +1,18 @@ -using System.Collections.Generic; -using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Collections.Generic; using System.Text; -using Microsoft.VisualStudio.TestTools.UnitTesting; namespace IrcTokens.Tests { [TestClass] - public class StatefulDecoderTests + public class StatefulDecoder { - private StatefulDecoder _decoder; + private IrcTokens.StatefulDecoder _decoder; [TestInitialize] public void TestInitialize() { - _decoder = new StatefulDecoder(); + _decoder = new IrcTokens.StatefulDecoder(); } [TestMethod] @@ -26,7 +25,7 @@ namespace IrcTokens.Tests Assert.AreEqual(1, lines.Count); var line = new Line("PRIVMSG #channel hello"); - CollectionAssert.AreEqual(new List<Line> {line}, lines); + CollectionAssert.AreEqual(new List<Line> { line }, lines); } [TestMethod] @@ -45,7 +44,7 @@ namespace IrcTokens.Tests public void TestEncoding() { var iso8859 = Encoding.GetEncoding("iso-8859-1"); - _decoder = new StatefulDecoder {Encoding = iso8859}; + _decoder = new IrcTokens.StatefulDecoder { Encoding = iso8859 }; var lines = _decoder.Push(iso8859.GetBytes("PRIVMSG #channel :hello Ç\r\n")); var line = new Line("PRIVMSG #channel :hello Ç"); Assert.IsTrue(line.Equals(lines[0])); @@ -55,7 +54,7 @@ namespace IrcTokens.Tests public void TestEncodingFallback() { var latin1 = Encoding.GetEncoding("iso-8859-1"); - _decoder = new StatefulDecoder {Encoding = null, Fallback = latin1}; + _decoder = new IrcTokens.StatefulDecoder { Encoding = null, Fallback = latin1 }; var lines = _decoder.Push(latin1.GetBytes("PRIVMSG #channel hélló\r\n")); Assert.AreEqual(1, lines.Count); Assert.IsTrue(new Line("PRIVMSG #channel hélló").Equals(lines[0])); diff --git a/IrcTokens/Tests/StatefulEncoderTests.cs b/IrcTokens/Tests/StatefulEncoder.cs index 477b38d..e3ed70d 100644 --- a/IrcTokens/Tests/StatefulEncoderTests.cs +++ b/IrcTokens/Tests/StatefulEncoder.cs @@ -1,18 +1,17 @@ -using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Text; -using Microsoft.VisualStudio.TestTools.UnitTesting; namespace IrcTokens.Tests { [TestClass] - public class StatefulEncoderTests + public class StatefulEncoder { - private StatefulEncoder _encoder; + private IrcTokens.StatefulEncoder _encoder; [TestInitialize] public void TestInitialize() { - _encoder = new StatefulEncoder(); + _encoder = new IrcTokens.StatefulEncoder(); } [TestMethod] @@ -64,7 +63,7 @@ namespace IrcTokens.Tests public void TestEncoding() { var iso8859 = Encoding.GetEncoding("iso-8859-1"); - _encoder = new StatefulEncoder {Encoding = iso8859}; + _encoder = new IrcTokens.StatefulEncoder { Encoding = iso8859 }; _encoder.Push(new Line("PRIVMSG #channel :hello Ç")); CollectionAssert.AreEqual(iso8859.GetBytes("PRIVMSG #channel :hello Ç\r\n"), _encoder.PendingBytes); } diff --git a/IrcTokens/Tests/TokenizationTests.cs b/IrcTokens/Tests/Tokenization.cs index 6d8a69d..c4970ed 100644 --- a/IrcTokens/Tests/TokenizationTests.cs +++ b/IrcTokens/Tests/Tokenization.cs @@ -1,10 +1,10 @@ -using System.Collections.Generic; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Collections.Generic; namespace IrcTokens.Tests { [TestClass] - public class TokenizationTests + public class Tokenization { [TestMethod] public void TestTagsMissing() @@ -87,14 +87,14 @@ namespace IrcTokens.Tests public void TestParamsTrailing() { var line = new Line("PRIVMSG #channel :hello world"); - CollectionAssert.AreEqual(new List<string> {"#channel", "hello world"}, line.Params); + CollectionAssert.AreEqual(new List<string> { "#channel", "hello world" }, line.Params); } [TestMethod] public void TestParamsOnlyTrailing() { var line = new Line("PRIVMSG :hello world"); - CollectionAssert.AreEqual(new List<string> {"hello world"}, line.Params); + CollectionAssert.AreEqual(new List<string> { "hello world" }, line.Params); } [TestMethod] @@ -109,10 +109,10 @@ namespace IrcTokens.Tests public void TestAllTokens() { var line = new Line("@id=123 :nick!user@host PRIVMSG #channel :hello world"); - CollectionAssert.AreEqual(new Dictionary<string, string> {{"id", "123"}}, line.Tags); + CollectionAssert.AreEqual(new Dictionary<string, string> { { "id", "123" } }, line.Tags); Assert.AreEqual("nick!user@host", line.Source); Assert.AreEqual("PRIVMSG", line.Command); - CollectionAssert.AreEqual(new List<string> {"#channel", "hello world"}, line.Params); + CollectionAssert.AreEqual(new List<string> { "#channel", "hello world" }, line.Params); } } } diff --git a/Sample/Client.cs b/Sample/Client.cs index e9e286f..b756adf 100644 --- a/Sample/Client.cs +++ b/Sample/Client.cs @@ -1,10 +1,9 @@ -using System; +using IrcTokens; +using System; using System.Collections.Generic; using System.Net.Sockets; -using System.Text; -using IrcTokens; -namespace Sample +namespace TokensSample { public class Client { @@ -25,15 +24,15 @@ namespace Sample { _socket.Connect("127.0.0.1", 6667); - Send(new Line {Command = "USER", Params = new List<string> {"username", "0", "*", "real name"}}); - Send(new Line {Command = "NICK", Params = new List<string> {"statefulbot"}}); + Send(new Line { Command = "USER", Params = new List<string> { "username", "0", "*", "real name" } }); + Send(new Line { Command = "NICK", Params = new List<string> { "tokensbot" } }); while (true) { var bytesReceived = _socket.Receive(_bytes); var lines = _decoder.Push(_bytes); - if (lines.Count == 0) + if (bytesReceived == 0) { Console.WriteLine("! disconnected"); _socket.Shutdown(SocketShutdown.Both); @@ -47,10 +46,10 @@ namespace Sample switch (line.Command) { case "PING": - Send(new Line {Command = "PONG", Params = line.Params}); + Send(new Line { Command = "PONG", Params = line.Params }); break; case "001": - Send(new Line {Command = "JOIN", Params = new List<string> {"#channel"}}); + Send(new Line { Command = "JOIN", Params = new List<string> { "#channel" } }); break; } } @@ -62,7 +61,9 @@ namespace Sample Console.WriteLine($"> {line.Format()}"); _encoder.Push(line); while (_encoder.PendingBytes.Length > 0) + { _encoder.Pop(_socket.Send(_encoder.PendingBytes)); + } } } } diff --git a/Sample/Program.cs b/Sample/Program.cs index 6800179..eda312f 100644 --- a/Sample/Program.cs +++ b/Sample/Program.cs @@ -1,8 +1,8 @@ -using System; +using IrcTokens; +using System; using System.Collections.Generic; -using IrcTokens; -namespace Sample +namespace TokensSample { public class Program { @@ -17,7 +17,7 @@ namespace Sample var line2 = new Line { Command = "USER", - Params = new List<string> {"user", "0", "*", "real name"} + Params = new List<string> { "user", "0", "*", "real name" } }; Console.WriteLine(line2); Console.WriteLine(line2.Format()); diff --git a/Sample/Sample.csproj b/Sample/TokensSample.csproj index 7c66734..7c66734 100644 --- a/Sample/Sample.csproj +++ b/Sample/TokensSample.csproj diff --git a/StatesSample/Program.cs b/StatesSample/Program.cs new file mode 100644 index 0000000..8fc42b8 --- /dev/null +++ b/StatesSample/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace StatesSample +{ + public static class Program + { + private static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/StatesSample/StatesSample.csproj b/StatesSample/StatesSample.csproj new file mode 100644 index 0000000..3107344 --- /dev/null +++ b/StatesSample/StatesSample.csproj @@ -0,0 +1,12 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>netcoreapp3.1</TargetFramework> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\IrcStates\IrcStates.csproj" /> + </ItemGroup> + +</Project> |