Merge pull request #438 from Licshee/using-StringEx

Using StringEx
This commit is contained in:
Gang Zhuo
2016-02-24 04:31:53 -05:00
14 changed files with 332 additions and 56 deletions
+2 -3
View File
@@ -18,10 +18,9 @@ namespace Shadowsocks.Controller
{
using (var sr = new StringReader(Resources.cn))
{
string line;
while ((line = sr.ReadLine()) != null)
foreach (var line in sr.NonWhiteSpaceLines())
{
if (line == "" || line[0] == '#')
if (line[0] == '#')
continue;
var pos = line.IndexOf('=');
@@ -247,7 +247,7 @@ namespace Shadowsocks.Controller
{
var currentHour = DateTime.Now.Hour;
filteredData = filteredData.Where(data =>
data.Timestamp != UnknownDateTime && data.Timestamp.Hour.Equals(currentHour)
data.Timestamp != UnknownDateTime && data.Timestamp.Hour == currentHour
);
if (filteredData.LongCount() == 0) return;
}
@@ -30,6 +30,7 @@ namespace Shadowsocks.Controller
}
}
private static readonly IEnumerable<char> IgnoredLineBegins = new[] { '!', '[' };
private void http_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
try
@@ -41,10 +42,9 @@ namespace Shadowsocks.Controller
string local = File.ReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8);
using (var sr = new StringReader(local))
{
string rule;
while ((rule = sr.ReadLine()) != null)
foreach (var rule in sr.NonWhiteSpaceLines())
{
if (rule == "" || rule[0] == '!' || rule[0] == '[')
if (rule.BeginWithAny(IgnoredLineBegins))
continue;
lines.Add(rule);
}
@@ -99,10 +99,9 @@ namespace Shadowsocks.Controller
List<string> valid_lines = new List<string>();
using (var sr = new StringReader(content))
{
string line;
while ((line = sr.ReadLine()) != null)
foreach (var line in sr.NonWhiteSpaceLines())
{
if (line == "" || line[0] == '!' || line[0] == '[')
if (line.BeginWithAny(IgnoredLineBegins))
continue;
valid_lines.Add(line);
}
@@ -442,6 +442,7 @@ namespace Shadowsocks.Controller
UpdatePACFromGFWListError(this, e);
}
private static readonly IEnumerable<char> IgnoredLineBegins = new[] { '!', '[' };
private void pacServer_UserRuleFileChanged(object sender, EventArgs e)
{
// TODO: this is a dirty hack. (from code GListUpdater.http_DownloadStringCompleted())
@@ -456,10 +457,9 @@ namespace Shadowsocks.Controller
string local = File.ReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8);
using (var sr = new StringReader(local))
{
string rule;
while ((rule = sr.ReadLine()) != null)
foreach (var rule in sr.NonWhiteSpaceLines())
{
if (rule == "" || rule[0] == '!' || rule[0] == '[')
if (rule.BeginWithAny(IgnoredLineBegins))
continue;
lines.Add(rule);
}
@@ -60,7 +60,7 @@ namespace Shadowsocks.Controller
else
{
string pacUrl;
if (config.useOnlinePac && !string.IsNullOrEmpty(config.pacUrl))
if (config.useOnlinePac && !config.pacUrl.IsNullOrEmpty())
pacUrl = config.pacUrl;
else
pacUrl = $"http://127.0.0.1:{config.localPort}/pac?t={GetTimestamp(DateTime.Now)}";
@@ -25,7 +25,7 @@ namespace Shadowsocks.Encryption
public static IEncryptor GetEncryptor(string method, string password, bool onetimeauth, bool isudp)
{
if (string.IsNullOrEmpty(method))
if (method.IsNullOrEmpty())
{
method = "aes-256-cfb";
}
+2 -2
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
<Costura />
<Caseless StringComparison="Ordinal" />
<Caseless StringComparison="Ordinal"/>
<Costura/>
</Weavers>
+2 -2
View File
@@ -124,13 +124,13 @@ namespace Shadowsocks.Model
private static void CheckPassword(string password)
{
if (string.IsNullOrEmpty(password))
if (password.IsNullOrEmpty())
throw new ArgumentException(I18N.GetString("Password can not be blank"));
}
private static void CheckServer(string server)
{
if (string.IsNullOrEmpty(server))
if (server.IsNullOrEmpty())
throw new ArgumentException(I18N.GetString("Server IP can not be blank"));
}
}
+2 -2
View File
@@ -29,11 +29,11 @@ namespace Shadowsocks.Model
public string FriendlyName()
{
if (string.IsNullOrEmpty(server))
if (server.IsNullOrEmpty())
{
return I18N.GetString("New server");
}
if (string.IsNullOrEmpty(remarks))
if (remarks.IsNullOrEmpty())
{
return server + ":" + server_port;
}
+237
View File
@@ -0,0 +1,237 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
static partial class StringEx
{
#pragma warning disable 1591
public static StringComparison GlobalDefaultComparison { get; set; } = StringComparison.Ordinal;
[ThreadStatic]
private static StringComparison? _DefaultComparison;
public static StringComparison DefaultComparison
{
get { return _DefaultComparison ?? GlobalDefaultComparison; }
set { _DefaultComparison = value; }
}
#region basic String methods
public static bool IsNullOrEmpty(this string value)
=> string.IsNullOrEmpty(value);
public static bool IsNullOrWhiteSpace(this string value)
=> string.IsNullOrWhiteSpace(value);
public static bool IsWhiteSpace(this string value)
{
foreach(var c in value)
{
if (char.IsWhiteSpace(c)) continue;
return false;
}
return true;
}
#if !PCL
public static string IsInterned(this string value)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
return string.IsInterned(value);
}
public static string Intern(this string value)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
return string.Intern(value);
}
#endif
#endregion
#region comparing
#region Is
public static bool Is(this string a, string b)
=> string.Equals(a, b, DefaultComparison);
public static bool Is(this string a, string b, StringComparison comparisonType)
=> string.Equals(a, b, comparisonType);
#endregion
#region BeginWith
public static bool BeginWith(this string s, char c)
{
if (s.IsNullOrEmpty()) return false;
return s[0] == c;
}
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
{
if (s.IsNullOrEmpty()) return false;
return chars.Contains(s[0]);
}
public static bool BeginWithAny(this string s, params char[] chars)
=> s.BeginWithAny(chars.AsEnumerable());
public static bool BeginWith(this string a, string b)
{
if (a == null || b == null) return false;
return a.StartsWith(b, DefaultComparison);
}
public static bool BeginWith(this string a, string b, StringComparison comparisonType)
{
if (a == null || b == null) return false;
return a.StartsWith(b, comparisonType);
}
#if !PCL
public static bool BeginWith(this string a, string b, bool ignoreCase, CultureInfo culture)
{
if (a == null || b == null) return false;
return a.StartsWith(b, ignoreCase, culture);
}
#endif
#endregion
#region FinishWith
public static bool FinishWith(this string s, char c)
{
if (s.IsNullOrEmpty()) return false;
return s.Last() == c;
}
public static bool FinishWithAny(this string s, IEnumerable<char> chars)
{
if (s.IsNullOrEmpty()) return false;
return chars.Contains(s.Last());
}
public static bool FinishWithAny(this string s, params char[] chars)
=> s.FinishWithAny(chars.AsEnumerable());
public static bool FinishWith(this string a, string b)
{
if (a == null || b == null) return false;
return a.EndsWith(b, DefaultComparison);
}
public static bool FinishWith(this string a, string b, StringComparison comparisonType)
{
if (a == null || b == null) return false;
return a.EndsWith(b, comparisonType);
}
#if !PCL
public static bool FinishWith(this string a, string b, bool ignoreCase, CultureInfo culture)
{
if (a == null || b == null) return false;
return a.EndsWith(b, ignoreCase, culture);
}
#endif
#endregion
#endregion
#region ToLines
public static IEnumerable<string> ToLines(this TextReader reader)
{
string line;
while ((line = reader.ReadLine()) != null)
yield return line;
}
public static IEnumerable<string> NonEmptyLines(this TextReader reader)
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line == "") continue;
yield return line;
}
}
public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader)
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.IsWhiteSpace()) continue;
yield return line;
}
}
#endregion
#region others
private static readonly char[][] Quotes = new[]
{
"\"\"",
"''",
"“”",
"‘’",
"『』",
"「」",
"〖〗",
"【】",
}.Select(s => s.ToCharArray()).ToArray();
public static string Enquote(this string value)
{
if (value == null)
return "(null)";
foreach (var pair in Quotes)
{
if (value.IndexOfAny(pair) < 0)
return pair[0] + value + pair[1];
}
return '"' + value.Replace("\\", @"\\").Replace("\"", @"\""") + '"';
}
public static string Replace(this string value, string find, string rep, StringComparison comparsionType)
{
if (find.IsNullOrEmpty())
throw new ArgumentException(null, nameof(find));
if (rep == null)
rep = "";
if (value.IsNullOrEmpty())
return value;
var sb = new StringBuilder(value.Length);
var last = 0;
var len = find.Length;
var idx = value.IndexOf(find, DefaultComparison);
while (idx != -1)
{
sb.Append(value.Substring(last, idx - last));
sb.Append(rep);
idx += len;
last = idx;
idx = value.IndexOf(find, idx, comparsionType);
}
sb.Append(value.Substring(last));
return sb.ToString();
}
public static string ReplaceEx(this string value, string find, string rep)
=> value.Replace(find, rep, DefaultComparison);
#endregion
}
@@ -630,11 +630,11 @@ namespace Shadowsocks.View
{
if (!onlinePACItem.Checked)
{
if (String.IsNullOrEmpty(controller.GetConfigurationCopy().pacUrl))
if (controller.GetConfigurationCopy().pacUrl.IsNullOrEmpty())
{
UpdateOnlinePACURLItem_Click(sender, e);
}
if (!String.IsNullOrEmpty(controller.GetConfigurationCopy().pacUrl))
if (!controller.GetConfigurationCopy().pacUrl.IsNullOrEmpty())
{
localPACItem.Checked = false;
onlinePACItem.Checked = true;
@@ -651,7 +651,7 @@ namespace Shadowsocks.View
I18N.GetString("Please input PAC Url"),
I18N.GetString("Edit Online PAC URL"),
origPacUrl, -1, -1);
if (!string.IsNullOrEmpty(pacUrl) && pacUrl != origPacUrl)
if (!pacUrl.IsNullOrEmpty() && pacUrl != origPacUrl)
{
controller.SavePACUrl(pacUrl);
}
+3 -2
View File
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Caseless.Fody" version="1.3.7" targetFramework="net40-client" developmentDependency="true" />
<package id="Costura.Fody" version="1.3.3.0" targetFramework="net4-client" developmentDependency="true" />
<package id="Caseless.Fody" version="1.4.1" targetFramework="net40-client" developmentDependency="true" />
<package id="Costura.Fody" version="1.3.3.0" targetFramework="net40-client" developmentDependency="true" />
<package id="Fody" version="1.29.4" targetFramework="net40-client" developmentDependency="true" />
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net40-client" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net40-client" />
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net40-client" />
<package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net4-client" />
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="net40-client" />
<package id="StringEx.CS" version="0.2" targetFramework="net40-client" />
<package id="System.Net.Http" version="2.0.20710.0" targetFramework="net40-client" />
</packages>
@@ -204,6 +204,7 @@
<Compile Include="Controller\Strategy\BalancingStrategy.cs" />
<Compile Include="Controller\Strategy\StrategyManager.cs" />
<Compile Include="Controller\Strategy\IStrategy.cs" />
<Compile Include="StringEx.cs" />
<Compile Include="Util\Util.cs" />
<Compile Include="View\ConfigForm.cs">
<SubType>Form</SubType>
@@ -333,6 +334,43 @@
</Target>
<Import Project="3rd\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('3rd\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
<Import Project="3rd\Fody.1.29.4\build\portable-net+sl+win+wpa+wp\Fody.targets" Condition="Exists('3rd\Fody.1.29.4\build\portable-net+sl+win+wpa+wp\Fody.targets')" />
<UsingTask TaskName="CosturaCleanup" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" TaskFactory="CodeTaskFactory">
<ParameterGroup>
<Config Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem" />
<Files Output="false" Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
</ParameterGroup>
<Task Evaluate="true">
<Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml" />
<Reference xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Include="System.Xml.Linq" />
<Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System" />
<Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.IO" />
<Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.Xml.Linq" />
<Code xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Type="Fragment" Language="cs">
<![CDATA[
var config = XElement.Load(Config.ItemSpec).Elements("Costura").FirstOrDefault();
if (config == null) return true;
var excludedAssemblies = new List<string>();
var attribute = config.Attribute("ExcludeAssemblies");
if (attribute != null)
foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty))
excludedAssemblies.Add(item);
var element = config.Element("ExcludeAssemblies");
if (element != null)
foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty))
excludedAssemblies.Add(item);
var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase));
foreach (var item in filesToCleanup)
File.Delete(item);
]]>
</Code></Task>
</UsingTask>
<Target Name="CleanReferenceCopyLocalPaths" AfterTargets="AfterBuild;NonWinFodyTarget">
<CosturaCleanup Config="FodyWeavers.xml" Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
+32 -30
View File
@@ -1,30 +1,32 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2012 for Windows Desktop
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shadowsocks-csharp", "shadowsocks-csharp\shadowsocks-csharp.csproj", "{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{45913187-0685-4903-B250-DCEF0479CD86}"
ProjectSection(ProjectDependencies) = postProject
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062} = {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.ActiveCfg = Debug|x86
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Build.0 = Debug|x86
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Deploy.0 = Debug|x86
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.ActiveCfg = Release|x86
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.Build.0 = Release|x86
{45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.ActiveCfg = Debug|x86
{45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.Build.0 = Debug|x86
{45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.ActiveCfg = Release|x86
{45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shadowsocks-csharp", "shadowsocks-csharp\shadowsocks-csharp.csproj", "{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{45913187-0685-4903-B250-DCEF0479CD86}"
ProjectSection(ProjectDependencies) = postProject
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062} = {8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.ActiveCfg = Debug|x86
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Build.0 = Debug|x86
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Deploy.0 = Debug|x86
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.ActiveCfg = Release|x86
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.Build.0 = Release|x86
{45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.ActiveCfg = Debug|x86
{45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.Build.0 = Debug|x86
{45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.ActiveCfg = Release|x86
{45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal