Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ctolkien committed Apr 30, 2020
1 parent 874b638 commit ef34172
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 9 deletions.
15 changes: 15 additions & 0 deletions Slugify.sln
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Slugify.Core", "src\Slugify
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Slugify.Core.Tests", "tests\Slugify.Core.Tests\Slugify.Core.Tests.csproj", "{A3717955-9FC4-41EB-B389-1A610D64B3B6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Slugify.Core.Benchmarks", "tests\Slugify.Core.Benchmarks\Slugify.Core.Benchmarks.csproj", "{A859F823-7992-4820-905C-640F3440BAF2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -44,13 +46,26 @@ Global
{A3717955-9FC4-41EB-B389-1A610D64B3B6}.Release|x64.Build.0 = Release|Any CPU
{A3717955-9FC4-41EB-B389-1A610D64B3B6}.Release|x86.ActiveCfg = Release|Any CPU
{A3717955-9FC4-41EB-B389-1A610D64B3B6}.Release|x86.Build.0 = Release|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Debug|x64.ActiveCfg = Debug|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Debug|x64.Build.0 = Debug|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Debug|x86.ActiveCfg = Debug|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Debug|x86.Build.0 = Debug|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Release|Any CPU.Build.0 = Release|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Release|x64.ActiveCfg = Release|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Release|x64.Build.0 = Release|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Release|x86.ActiveCfg = Release|Any CPU
{A859F823-7992-4820-905C-640F3440BAF2}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CC5D3071-57A3-442C-8ACC-E543DA0A8E20} = {321AAEAA-F675-4B15-80B5-3FF2E6A15602}
{A3717955-9FC4-41EB-B389-1A610D64B3B6} = {28DEE6D8-053D-4364-9DD5-F3744E58CF54}
{A859F823-7992-4820-905C-640F3440BAF2} = {28DEE6D8-053D-4364-9DD5-F3744E58CF54}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {189B8864-9AE7-4F2D-BFAC-5368F94F26E2}
Expand Down
75 changes: 69 additions & 6 deletions src/Slugify.Core/SlugHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace Slugify
{
Expand Down Expand Up @@ -45,6 +46,72 @@ public string GenerateSlug(string inputString)
return inputString;
}

public string GenerateSlug2(string inputString)
{
if (_config.TrimWhitespace)
{
inputString = inputString.Trim();
}

if (_config.ForceLowerCase)
{
inputString = inputString.ToLower();
}

inputString = CleanWhiteSpace(inputString, _config.CollapseWhiteSpace);
inputString = ApplyReplacements(inputString, _config.StringReplacements);
inputString = RemoveDiacritics(inputString);
inputString = DeleteCharacters(inputString, _config.DeniedCharactersRegex);

if (_config.CollapseDashes)
{
inputString = Regex.Replace(inputString, "--+", "-");
}

return inputString;

string CleanWhiteSpace(string str, bool collapse)
{
return Regex.Replace(str, collapse ? @"\s+" : @"\s", " ");
}

string RemoveDiacritics(string str)
{
var stFormD = str.Normalize(NormalizationForm.FormD);
var sb = new StringBuilder(stFormD.Length);


for (var ich = 0; ich < stFormD.Length; ich++)
{
var uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
if (uc != UnicodeCategory.NonSpacingMark)
{
sb.Append(stFormD[ich]);
}
}

return sb.ToString().Normalize(NormalizationForm.FormC);
}


string ApplyReplacements(string str, Dictionary<string, string> replacements)
{
foreach (var replacement in replacements)
{
str = str.Replace(replacement.Key, replacement.Value);
}

return str;
}

string DeleteCharacters(string str, string regex)
{
return Regex.Replace(str, regex, "");
}

}


protected string CleanWhiteSpace(string str, bool collapse)
{
return Regex.Replace(str, collapse ? @"\s+" : @"\s", " ");
Expand Down Expand Up @@ -90,15 +157,11 @@ protected string DeleteCharacters(string str, string regex)
/// </summary>
public class Config
{
public Config()
{
StringReplacements = new Dictionary<string, string>
public Dictionary<string, string> StringReplacements { get; set; } = new Dictionary<string, string>
{
{ " ", "-" }
};
}

public Dictionary<string, string> StringReplacements { get; set; }

public bool ForceLowerCase { get; set; } = true;
public bool CollapseWhiteSpace { get; set; } = true;
public string DeniedCharactersRegex { get; set; } = @"[^a-zA-Z0-9\-\._]";
Expand Down
1 change: 1 addition & 0 deletions src/Slugify.Core/Slugify.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ With default settings, you will get an hyphenized, lowercase, alphanumeric versi
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Memory" Version="4.5.4" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
``` ini

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.778 (1909/November2018Update/19H2)
Intel Core i9-9900K CPU 3.60GHz (Coffee Lake), 1 CPU, 16 logical and 8 physical cores
.NET Core SDK=3.1.201
[Host] : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
DefaultJob : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT


```
| Method | N | word | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|--------- |-- |--------------------- |-----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:|
| **Baseline** | **1** | **Hello** | **660.0 ns** | **2.01 ns** | **1.78 ns** | **1.00** | **0.00** | **0.0734** | **-** | **-** | **616 B** |
| Improved | 1 | Hello | 643.8 ns | 12.74 ns | 11.92 ns | 0.98 | 0.02 | 0.0553 | - | - | 464 B |
| | | | | | | | | | | | |
| **Baseline** | **1** | **lorem(...)oot!! [40]** | **4,174.1 ns** | **11.46 ns** | **10.72 ns** | **1.00** | **0.00** | **0.4501** | **-** | **-** | **3824 B** |
| Improved | 1 | lorem(...)oot!! [40] | 3,924.9 ns | 7.03 ns | 5.87 ns | 0.94 | 0.00 | 0.3967 | - | - | 3360 B |
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,N,word,Mean,Error,StdDev,Ratio,RatioSD,Gen 0,Gen 1,Gen 2,Allocated
Baseline,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,Hello,660.0 ns,2.01 ns,1.78 ns,1.00,0.00,0.0734,0.0000,0.0000,616 B
Improved,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,Hello,643.8 ns,12.74 ns,11.92 ns,0.98,0.02,0.0553,0.0000,0.0000,464 B
Baseline,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,lorem(...)oot!! [40],"4,174.1 ns",11.46 ns,10.72 ns,1.00,0.00,0.4501,0.0000,0.0000,3824 B
Improved,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,lorem(...)oot!! [40],"3,924.9 ns",7.03 ns,5.87 ns,0.94,0.00,0.3967,0.0000,0.0000,3360 B
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Slugify.Core.Benchmarks.SlugifyBenchmarks-20200430-160656</title>

<style type="text/css">
table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
td, th { padding: 6px 13px; border: 1px solid #ddd; text-align: right; }
tr { background-color: #fff; border-top: 1px solid #ccc; }
tr:nth-child(even) { background: #f8f8f8; }
</style>
</head>
<body>
<pre><code>
BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.778 (1909/November2018Update/19H2)
Intel Core i9-9900K CPU 3.60GHz (Coffee Lake), 1 CPU, 16 logical and 8 physical cores
.NET Core SDK=3.1.201
[Host] : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
DefaultJob : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
</code></pre>
<pre><code></code></pre>

<table>
<thead><tr><th>Method</th><th>N</th><th> word</th><th>Mean</th><th>Error</th><th>StdDev</th><th>Ratio</th><th>RatioSD</th><th>Gen 0</th><th>Gen 1</th><th>Gen 2</th><th>Allocated</th>
</tr>
</thead><tbody><tr><td>Baseline</td><td>1</td><td>Hello</td><td>660.0 ns</td><td>2.01 ns</td><td>1.78 ns</td><td>1.00</td><td>0.00</td><td>0.0734</td><td>-</td><td>-</td><td>616 B</td>
</tr><tr><td>Improved</td><td>1</td><td>Hello</td><td>643.8 ns</td><td>12.74 ns</td><td>11.92 ns</td><td>0.98</td><td>0.02</td><td>0.0553</td><td>-</td><td>-</td><td>464 B</td>
</tr><tr><td>Baseline</td><td>1</td><td>lorem(...)oot!! [40]</td><td>4,174.1 ns</td><td>11.46 ns</td><td>10.72 ns</td><td>1.00</td><td>0.00</td><td>0.4501</td><td>-</td><td>-</td><td>3824 B</td>
</tr><tr><td>Improved</td><td>1</td><td>lorem(...)oot!! [40]</td><td>3,924.9 ns</td><td>7.03 ns</td><td>5.87 ns</td><td>0.94</td><td>0.00</td><td>0.3967</td><td>-</td><td>-</td><td>3360 B</td>
</tr></tbody></table>
</body>
</html>
55 changes: 55 additions & 0 deletions tests/Slugify.Core.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Slugify.Core.Benchmarks
{
internal class Program
{
private static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<SlugifyBenchmarks>();
}
}

[MemoryDiagnoser]
public class SlugifyBenchmarks
{
private SlugHelper _slugHelper;

[GlobalSetup]
public void GlobalSetup()
{
_slugHelper = new SlugHelper();
}

[Params(1)]
public int N;

[Params("Hello", "lorem & ipsome Some Other thing!_ woot!!")]
public string word;

[Benchmark(Baseline = true)]
public void Baseline()
{
for (int i = 0; i < N; i++)
{
_slugHelper.GenerateSlug(word);
}
}

[Benchmark]
public void Improved()
{
for (int i = 0; i < N; i++)
{
_slugHelper.GenerateSlug2(word);
}
}


}
}
17 changes: 17 additions & 0 deletions tests/Slugify.Core.Benchmarks/Slugify.Core.Benchmarks.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Slugify.Core\Slugify.Core.csproj" />
</ItemGroup>


</Project>
6 changes: 3 additions & 3 deletions tests/Slugify.Core.Tests/SlugHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public void TestEmptyConfig()
var config = new SlugHelper.Config();
Assert.True(config.ForceLowerCase);
Assert.True(config.CollapseWhiteSpace);
Assert.Equal(1, config.StringReplacements.Count);
Assert.Single(config.StringReplacements);
Assert.NotNull(new Regex(config.DeniedCharactersRegex));
}

Expand All @@ -21,7 +21,7 @@ public void TestDefaultConfig()
{
var config = new SlugHelper.Config();

Assert.Equal(1, config.StringReplacements.Count);
Assert.Single(config.StringReplacements);
Assert.Equal("-", config.StringReplacements[" "]);
}

Expand All @@ -46,7 +46,7 @@ public void TestLoweCaseEnforcement()

var helper = new SlugHelper();

Assert.Equal(expected, helper.GenerateSlug(original));
Assert.Equal(expected, helper.GenerateSlug2(original));
}

[Fact]
Expand Down

0 comments on commit ef34172

Please sign in to comment.