├── AhoCorasick
├── key.snk
├── AhoCorasick.csproj
├── Extensions.cs
├── Trie.cs
├── AhoCorasick.cs
└── CharComparer.cs
├── .github
└── dependabot.yml
├── .nuget
└── packages.config
├── LICENSE
├── AhoCorasick.Tests
├── AhoCorasick.Tests.csproj
├── CharComparerTests.cs
└── UnitTests.cs
├── AhoCorasick.SqlClr
├── AhoCorasick.SqlClr.sln
├── AhoCorasick.SqlClr.sqlproj
├── Contains.cs
└── dist
│ └── AhoCorasick.SqlClr_Create.sql
├── AhoCorasick.sln
├── appveyor.yml
├── .gitignore
└── README.md
/AhoCorasick/key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mganss/AhoCorasick/HEAD/AhoCorasick/key.snk
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: nuget
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "04:00"
8 | open-pull-requests-limit: 10
9 |
--------------------------------------------------------------------------------
/.nuget/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Michael Ganss
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/AhoCorasick.Tests/AhoCorasick.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net462;net6.0
4 | Ganss.Text.Tests
5 | true
6 | opencover
7 | ../coverage.xml
8 | [AhoCorasick]*
9 |
10 |
11 |
12 |
13 |
14 |
15 | all
16 | runtime; build; native; contentfiles; analyzers
17 |
18 |
19 |
20 |
21 |
22 | all
23 | runtime; build; native; contentfiles; analyzers; buildtransitive
24 |
25 |
26 |
--------------------------------------------------------------------------------
/AhoCorasick.SqlClr/AhoCorasick.SqlClr.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "AhoCorasick.SqlClr", "AhoCorasick.SqlClr.sqlproj", "{FBC73EEF-133B-492B-9EBB-77E7484F3485}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {FBC73EEF-133B-492B-9EBB-77E7484F3485}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {FBC73EEF-133B-492B-9EBB-77E7484F3485}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {FBC73EEF-133B-492B-9EBB-77E7484F3485}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
17 | {FBC73EEF-133B-492B-9EBB-77E7484F3485}.Release|Any CPU.ActiveCfg = Release|Any CPU
18 | {FBC73EEF-133B-492B-9EBB-77E7484F3485}.Release|Any CPU.Build.0 = Release|Any CPU
19 | {FBC73EEF-133B-492B-9EBB-77E7484F3485}.Release|Any CPU.Deploy.0 = Release|Any CPU
20 | EndGlobalSection
21 | GlobalSection(SolutionProperties) = preSolution
22 | HideSolutionNode = FALSE
23 | EndGlobalSection
24 | EndGlobal
25 |
--------------------------------------------------------------------------------
/AhoCorasick.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26730.12
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AhoCorasick", "AhoCorasick\AhoCorasick.csproj", "{A1F19E27-06C8-4DB1-94CE-24B4F10330DF}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AhoCorasick.Tests", "AhoCorasick.Tests\AhoCorasick.Tests.csproj", "{860F4149-D7F3-495A-99BE-8AC3FBAE4176}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {A1F19E27-06C8-4DB1-94CE-24B4F10330DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {A1F19E27-06C8-4DB1-94CE-24B4F10330DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {A1F19E27-06C8-4DB1-94CE-24B4F10330DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {A1F19E27-06C8-4DB1-94CE-24B4F10330DF}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {860F4149-D7F3-495A-99BE-8AC3FBAE4176}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {860F4149-D7F3-495A-99BE-8AC3FBAE4176}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {860F4149-D7F3-495A-99BE-8AC3FBAE4176}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {860F4149-D7F3-495A-99BE-8AC3FBAE4176}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {12FCD39C-9278-4D4D-8438-9A0FCDCA85F3}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 2.0.{build}
2 | skip_tags: true
3 | image: Visual Studio 2022
4 | environment:
5 | access_token:
6 | secure: Eq6BjtZ80BXKLwFMg76IjuQAvbLjbojIF/X/ARouGVhxPneJtgDfCXMPNgJ7KBKq
7 | sonar_token:
8 | secure: W7pHKhuTW6Lh8WlXJNTOIaOzeuxLi+H6Nqmnm4pr28jM6jyIpOZ+1r10lIQi0eCA
9 | JAVA_HOME: C:\Program Files\Java\jdk19
10 | build_script:
11 | - dotnet restore
12 | - dotnet pack --include-symbols --include-source -c Release AhoCorasick
13 | test_script:
14 | - ps: |
15 | if (-not $env:APPVEYOR_PULL_REQUEST_NUMBER) {
16 | dotnet tool install --global dotnet-sonarscanner
17 | dotnet sonarscanner begin /k:"mganss_AhoCorasick" /v:$env:APPVEYOR_BUILD_VERSION /o:"mganss-github" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.login="$env:sonar_token" /d:sonar.cs.opencover.reportsPaths="$($env:APPVEYOR_BUILD_FOLDER)\coverage.xml" /d:sonar.coverage.exclusions="**/Program.cs"
18 | dotnet build
19 | }
20 | - dotnet test /p:CollectCoverage=true AhoCorasick.Tests\AhoCorasick.Tests.csproj /p:Include="[AhoCorasick]*" -f net6.0
21 | - ps: cp coverage.*.xml ./coverage.xml
22 | - ps: |
23 | if (-not $env:APPVEYOR_PULL_REQUEST_NUMBER) {
24 | dotnet sonarscanner end /d:sonar.login="$env:sonar_token"
25 | }
26 | - pip install codecov
27 | - codecov -f "coverage.xml"
28 | artifacts:
29 | - path: 'AhoCorasick\**\*.*nupkg'
30 | deploy:
31 | - provider: GitHub
32 | tag: v$(APPVEYOR_BUILD_VERSION)
33 | release: $(APPVEYOR_BUILD_VERSION)
34 | description: '$(APPVEYOR_REPO_COMMIT_MESSAGE)'
35 | auth_token:
36 | secure: Eq6BjtZ80BXKLwFMg76IjuQAvbLjbojIF/X/ARouGVhxPneJtgDfCXMPNgJ7KBKq
37 | draft: true
38 | on:
39 | branch: master
40 |
--------------------------------------------------------------------------------
/AhoCorasick/AhoCorasick.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Ganss.Text
4 | AhoCorasick
5 | Implements the Aho-Corasick string search algorithm
6 | Copyright 2013-$([System.DateTime]::Now.Year) Michael Ganss
7 | 1.0.0
8 | 2.0.0.0
9 | $(AppVeyor_Build_Version).0
10 | $(AppVeyor_Build_Version)
11 | Michael Ganss
12 | net40;netstandard2.0
13 | AhoCorasick
14 | AhoCorasick
15 | aho-corasick;aho;corasick;string;search;match;substring
16 | https://github.com/mganss/AhoCorasick
17 | https://github.com/mganss/AhoCorasick/blob/master/LICENSE
18 | README.md
19 | git
20 | git://github.com/mganss/AhoCorasick
21 | Ganss.Text
22 | true
23 | bin\$(Configuration)\$(TargetFramework)\AhoCorasick.xml
24 | true
25 | key.snk
26 | snupkg
27 | true
28 | true
29 | true
30 | snupkg
31 | latest
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/AhoCorasick/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace Ganss.Text
4 | {
5 | ///
6 | /// Provides extension methods.
7 | ///
8 | public static class Extensions
9 | {
10 | ///
11 | /// Determines whether this instance contains the specified words.
12 | ///
13 | /// The text.
14 | /// The words.
15 | /// The matched words.
16 | public static IEnumerable Contains(this string text, IEnumerable words)
17 | {
18 | return new AhoCorasick(words).Search(text);
19 | }
20 |
21 | ///
22 | /// Determines whether this instance contains the specified words.
23 | ///
24 | /// The text.
25 | /// The words.
26 | /// The matched words.
27 | public static IEnumerable Contains(this string text, params string[] words)
28 | {
29 | return new AhoCorasick(words).Search(text);
30 | }
31 |
32 | ///
33 | /// Determines whether this instance contains the specified words.
34 | ///
35 | /// The text.
36 | /// The comparer used to compare individual characters.
37 | /// The words.
38 | /// The matched words.
39 | public static IEnumerable Contains(this string text, IEqualityComparer comparer, IEnumerable words)
40 | {
41 | return new AhoCorasick(comparer, words).Search(text);
42 | }
43 |
44 | ///
45 | /// Determines whether this instance contains the specified words.
46 | ///
47 | /// The text.
48 | /// The comparer used to compare individual characters.
49 | /// The words.
50 | /// The matched words.
51 | public static IEnumerable Contains(this string text, IEqualityComparer comparer, params string[] words)
52 | {
53 | return new AhoCorasick(comparer, words).Search(text);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | [Bb]in/
16 | [Oo]bj/
17 |
18 | # MSTest test Results
19 | [Tt]est[Rr]esult*/
20 | [Bb]uild[Ll]og.*
21 |
22 | *_i.c
23 | *_p.c
24 | *.ilk
25 | *.meta
26 | *.obj
27 | *.pch
28 | *.pdb
29 | *.pgc
30 | *.pgd
31 | *.rsp
32 | *.sbr
33 | *.tlb
34 | *.tli
35 | *.tlh
36 | *.tmp
37 | *.tmp_proj
38 | *.log
39 | *.vspscc
40 | *.vssscc
41 | .builds
42 | *.pidb
43 | *.log
44 | *.scc
45 |
46 | # Visual C++ cache files
47 | ipch/
48 | *.aps
49 | *.ncb
50 | *.opensdf
51 | *.sdf
52 | *.cachefile
53 |
54 | # Visual Studio profiler
55 | *.psess
56 | *.vsp
57 | *.vspx
58 |
59 | # Guidance Automation Toolkit
60 | *.gpState
61 |
62 | # ReSharper is a .NET coding add-in
63 | _ReSharper*/
64 | *.[Rr]e[Ss]harper
65 |
66 | # TeamCity is a build add-in
67 | _TeamCity*
68 |
69 | # DotCover is a Code Coverage Tool
70 | *.dotCover
71 |
72 | # NCrunch
73 | *.ncrunch*
74 | .*crunch*.local.xml
75 |
76 | # Installshield output folder
77 | [Ee]xpress/
78 |
79 | # DocProject is a documentation generator add-in
80 | DocProject/buildhelp/
81 | DocProject/Help/*.HxT
82 | DocProject/Help/*.HxC
83 | DocProject/Help/*.hhc
84 | DocProject/Help/*.hhk
85 | DocProject/Help/*.hhp
86 | DocProject/Help/Html2
87 | DocProject/Help/html
88 |
89 | # Click-Once directory
90 | publish/
91 |
92 | # Publish Web Output
93 | *.Publish.xml
94 | *.pubxml
95 |
96 | # NuGet Packages Directory
97 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
98 | packages/
99 |
100 | # Windows Azure Build Output
101 | csx
102 | *.build.csdef
103 |
104 | # Windows Store app package directory
105 | AppPackages/
106 |
107 | # Others
108 | sql/
109 | *.Cache
110 | ClientBin/
111 | [Ss]tyle[Cc]op.*
112 | ~$*
113 | *~
114 | *.dbmdl
115 | *.[Pp]ublish.xml
116 | *.pfx
117 | *.publishsettings
118 |
119 | # RIA/Silverlight projects
120 | Generated_Code/
121 |
122 | # Backup & report files from converting an old project file to a newer
123 | # Visual Studio version. Backup files are not needed, because we have git ;-)
124 | _UpgradeReport_Files/
125 | Backup*/
126 | UpgradeLog*.XML
127 | UpgradeLog*.htm
128 |
129 | # SQL Server files
130 | App_Data/*.mdf
131 | App_Data/*.ldf
132 |
133 | # =========================
134 | # Windows detritus
135 | # =========================
136 |
137 | # Windows image file caches
138 | Thumbs.db
139 | ehthumbs.db
140 |
141 | # Folder config file
142 | Desktop.ini
143 |
144 | # Recycle Bin used on file shares
145 | $RECYCLE.BIN/
146 |
147 | # Mac crap
148 | .DS_Store
149 |
150 | *.nupkg
151 | TestResult.xml
152 | coverage.xml
153 | .vs/
154 | /OpenCover
155 |
--------------------------------------------------------------------------------
/AhoCorasick.Tests/CharComparerTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Globalization;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 |
10 | namespace Ganss.Text.Tests
11 | {
12 | public class CharComparerTests
13 | {
14 | const char SmallDotlessI = '\u0131';
15 | const char CapitalIWithDot = '\u0130';
16 | const char CapitalSharpS = '\u1e9e';
17 | const char LatinSmallCapitalR = '\u0280';
18 | const char LatinLetterYR = '\u01a6';
19 |
20 | [Test]
21 | public void OrdinalTest()
22 | {
23 | var c = CharComparer.Ordinal;
24 | Assert.That(c.Equals('i', 'i'), Is.True);
25 | Assert.That(c.Equals(SmallDotlessI, 'i'), Is.False);
26 | Assert.That(c.Equals('ß', CapitalSharpS), Is.False);
27 | Assert.That(c.Equals(LatinSmallCapitalR, LatinLetterYR), Is.False);
28 |
29 | c = CharComparer.OrdinalIgnoreCase;
30 | Assert.That(c.Equals('i', 'I'), Is.True);
31 | Assert.That(c.Equals(SmallDotlessI, 'i'), Is.False);
32 | Assert.That(c.Equals(SmallDotlessI, 'I'), Is.False);
33 | Assert.That(c.Equals('ß', CapitalSharpS), Is.False);
34 | Assert.That(c.Equals(LatinSmallCapitalR, LatinLetterYR), Is.True);
35 | }
36 |
37 | [Test]
38 | public void InvariantTest()
39 | {
40 | var c = CharComparer.InvariantCulture;
41 | Assert.That(c.Equals('i', 'i'), Is.True);
42 | Assert.That(c.Equals(SmallDotlessI, 'i'), Is.False);
43 | Assert.That(c.Equals('ß', CapitalSharpS), Is.False);
44 | Assert.That(c.Equals(LatinSmallCapitalR, LatinLetterYR), Is.False);
45 |
46 | c = CharComparer.InvariantCultureIgnoreCase;
47 | Assert.That(c.Equals('i', 'I'), Is.True);
48 | Assert.That(c.Equals(SmallDotlessI, 'i'), Is.False);
49 | Assert.That(c.Equals(SmallDotlessI, 'I'), Is.False);
50 | Assert.That(c.Equals('ß', CapitalSharpS), Is.True);
51 | }
52 |
53 | [Test]
54 | public void CultureTest()
55 | {
56 | CultureInfo.CurrentCulture = new CultureInfo("tr-TR");
57 | var c = CharComparer.CurrentCulture;
58 | Assert.That(c.Equals('i', 'i'), Is.True);
59 | Assert.That(c.Equals(SmallDotlessI, 'i'), Is.False);
60 | Assert.That(c.Equals('ß', CapitalSharpS), Is.False);
61 | Assert.That(c.Equals(LatinSmallCapitalR, LatinLetterYR), Is.False);
62 |
63 | c = CharComparer.CurrentCultureIgnoreCase;
64 | Assert.That(c.Equals('i', 'I'), Is.False);
65 | Assert.That(c.Equals(SmallDotlessI, 'i'), Is.False);
66 | Assert.That(c.Equals(SmallDotlessI, 'I'), Is.True);
67 | Assert.That(c.Equals('i', CapitalIWithDot), Is.True);
68 | Assert.That(c.Equals('ß', CapitalSharpS), Is.True);
69 |
70 | Assert.That(c.GetHashCode('i'), Is.EqualTo(c.GetHashCode(CapitalIWithDot)));
71 | Assert.That(c.GetHashCode(SmallDotlessI), Is.EqualTo(c.GetHashCode('I')));
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/AhoCorasick/Trie.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace Ganss.Text
4 | {
5 | ///
6 | /// A Trie.
7 | ///
8 | public class Trie
9 | {
10 | ///
11 | /// Gets or sets the child nodes.
12 | ///
13 | ///
14 | /// The child nodes.
15 | ///
16 | public Dictionary Next { get; set; }
17 |
18 | ///
19 | /// Gets or sets a value indicating whether this instance represents a word in the dictionary.
20 | ///
21 | ///
22 | /// true if this instance is a word in the dictionary; otherwise, false.
23 | ///
24 | public bool IsWord { get; set; }
25 |
26 | ///
27 | /// Gets or sets the failure node.
28 | ///
29 | ///
30 | /// The failure node.
31 | ///
32 | public Trie Fail { get; set; }
33 |
34 | ///
35 | /// Gets or sets the parent node.
36 | ///
37 | ///
38 | /// The parent node.
39 | ///
40 | public Trie Parent { get; set; }
41 |
42 | ///
43 | /// Gets the word prefix this node represents.
44 | ///
45 | ///
46 | /// The word prefix.
47 | ///
48 | public string Word { get; private set; }
49 |
50 | ///
51 | /// Initializes a new instance of the class.
52 | ///
53 | public Trie()
54 | {
55 | Word = "";
56 | Next = new Dictionary();
57 | }
58 |
59 | ///
60 | /// Initializes a new instance of the class.
61 | ///
62 | /// The comparer used to compare individual characters.
63 | public Trie(IEqualityComparer comparer)
64 | {
65 | Word = "";
66 | Next = new Dictionary(comparer);
67 | }
68 |
69 | ///
70 | /// Adds the specified word to the trie.
71 | ///
72 | /// The word.
73 | ///
74 | public virtual Trie Add(string word)
75 | {
76 | var c = word[0];
77 |
78 | if (!Next.TryGetValue(c, out Trie node))
79 | Next[c] = node = new Trie(Next.Comparer) { Parent = this, Word = Word + c };
80 |
81 | if (word.Length > 1)
82 | return node.Add(word.Substring(1));
83 | else
84 | node.IsWord = true;
85 |
86 | return node;
87 | }
88 |
89 | ///
90 | /// Finds the failure node for a specified suffix within the given range of indices.
91 | ///
92 | /// The string containing the suffix.
93 | /// The start index of the suffix within the string.
94 | /// The end index (exclusive) of the suffix within the string.
95 | /// The failure node or null if no failure node is found.
96 |
97 | public virtual Trie ExploreFailLink(string word, int startIndex, int endIndex)
98 | {
99 | var node = this;
100 |
101 | for (int i = startIndex; i < endIndex; i++)
102 | {
103 | if (!node.Next.TryGetValue(word[i], out node))
104 | {
105 | return null;
106 | }
107 | }
108 |
109 | return node;
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/AhoCorasick.SqlClr/AhoCorasick.SqlClr.sqlproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | AhoCorasick.SqlClr
8 | 2.0
9 | 4.1
10 | {fbc73eef-133b-492b-9ebb-77e7484f3485}
11 | Microsoft.Data.Tools.Schema.Sql.Sql120DatabaseSchemaProvider
12 | Database
13 |
14 |
15 | AhoCorasick.SqlClr
16 | AhoCorasick.SqlClr
17 | 1033, CI
18 | BySchemaAndSchemaType
19 | True
20 | v4.0
21 | CS
22 | Properties
23 | False
24 | True
25 | True
26 | True
27 |
28 |
29 | bin\Release\
30 | $(MSBuildProjectName).sql
31 | False
32 | pdbonly
33 | true
34 | false
35 | true
36 | prompt
37 | 4
38 | NET40
39 |
40 |
41 | bin\Debug\
42 | $(MSBuildProjectName).sql
43 | false
44 | true
45 | full
46 | false
47 | true
48 | true
49 | prompt
50 | 4
51 | NET40
52 |
53 |
54 | 11.0
55 |
56 | True
57 | 11.0
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | AhoCorasick.cs
67 |
68 |
69 | CharComparer.cs
70 |
71 |
72 | Trie.cs
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/AhoCorasick.Tests/UnitTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Ganss.Text;
4 | using System.Collections.Generic;
5 | using NUnit.Framework;
6 | using System.Globalization;
7 |
8 | namespace Ganss.Text.Tests
9 | {
10 | public class WordMatchList: List
11 | {
12 | public void Add(int index, string word)
13 | {
14 | Add(new WordMatch { Index = index, Word = word });
15 | }
16 | }
17 |
18 | public class UnitTests
19 | {
20 | [Test]
21 | public void SearchWikipediaTest()
22 | {
23 | // from https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm
24 | var ac = new AhoCorasick("a", "ab", "bab", "bc", "bca", "c", "caa");
25 | var m = ac.Search("abccab").ToList();
26 | var expected = new WordMatchList { { 0, "a" }, { 0, "ab" }, { 1, "bc" }, { 2, "c" }, { 3, "c" }, { 4, "a" }, { 4, "ab" } };
27 | Assert.That(m, Is.EquivalentTo(expected));
28 | }
29 |
30 | [Test]
31 | public void SimpleTest()
32 | {
33 | var ac = new AhoCorasick("a");
34 | Assert.That(ac.Search("a").ToList(), Is.EquivalentTo(new WordMatchList { { 0, "a" } }));
35 | Assert.That(ac.Search("b"), Is.Empty);
36 | }
37 |
38 | [Test]
39 | public void SearchNullEmptyTest()
40 | {
41 | var ac = new AhoCorasick("a");
42 | var m = ac.Search(null).ToList();
43 | Assert.That(m, Is.Empty);
44 | m = ac.Search("").ToList();
45 | Assert.That(m, Is.Empty);
46 | }
47 |
48 | [Test]
49 | public void SearchMultipleTest()
50 | {
51 | var ac = new AhoCorasick("her", "their", "eye", "iris", "he", "is", "si");
52 | var m = ac.Search("theye iris irisis").ToList();
53 | var expected = new WordMatchList { { 1, "he" }, { 2, "eye" }, { 6, "iris" }, { 8, "is" }, { 11, "iris" }, { 13, "is" }, { 14, "si" }, { 15, "is" } };
54 | Assert.That(m, Is.EquivalentTo(expected));
55 | }
56 |
57 | [Test]
58 | public void SearchIvankTest()
59 | {
60 | // from http://blog.ivank.net/aho-corasick-algorithm-in-as3.html
61 | var ac = new AhoCorasick("take", "fast", "sofa");
62 | var m = ac.Search("takeso fasofast fassofatake sosso sofastake so").ToList();
63 | var expected = new WordMatchList { { 0, "take" }, { 9, "sofa" }, { 11, "fast" }, { 19, "sofa" }, { 23, "take" }, { 34, "sofa" }, { 36, "fast" }, { 39, "take" } };
64 | Assert.That(m, Is.EquivalentTo(expected));
65 | }
66 |
67 | [Test]
68 | public void StringExtensionTest()
69 | {
70 | var m = "abc".Contains("abd", "bc", "ab").ToList();
71 | Assert.That(m, Is.EquivalentTo(new WordMatchList { { 0, "ab" }, { 1, "bc" } }));
72 | m = "abc".Contains(new List { "abd", "bc", "ab" }).ToList();
73 | Assert.That(m, Is.EquivalentTo(new WordMatchList { { 0, "ab" }, { 1, "bc" } }));
74 | m = "ABC".Contains(CharComparer.OrdinalIgnoreCase, "abd", "bc", "ab").ToList();
75 | Assert.That(m, Is.EquivalentTo(new WordMatchList { { 0, "ab" }, { 1, "bc" } }));
76 | m = "ABC".Contains(CharComparer.OrdinalIgnoreCase, new List { "abd", "bc", "ab" }).ToList();
77 | Assert.That(m, Is.EquivalentTo(new WordMatchList { { 0, "ab" }, { 1, "bc" } }));
78 | }
79 |
80 | [Test]
81 | public void UpperCaseTest()
82 | {
83 | var ac = new AhoCorasick("a", "ab", "bab", "bC", "bca", "c", "caa");
84 | var m = ac.Search("abCcab").ToList();
85 | var expected = new WordMatchList { { 0, "a" }, { 0, "ab" }, { 1, "bC" }, { 3, "c" }, { 4, "a" }, { 4, "ab" } };
86 | Assert.That(m, Is.EquivalentTo(expected));
87 | }
88 |
89 | [Test]
90 | public void OrdinalIgnoreCaseTest()
91 | {
92 | var ac = new AhoCorasick(CharComparer.OrdinalIgnoreCase, "a", "ab", "bab", "bC", "bca", "c", "caa");
93 | var m = ac.Search("abCcab").ToList();
94 | var expected = new WordMatchList { { 0, "a" }, { 0, "ab" }, { 1, "bC" }, { 2, "c" }, { 3, "c" }, { 4, "a" }, { 4, "ab" } };
95 | Assert.That(m, Is.EquivalentTo(expected));
96 | }
97 |
98 | [Test]
99 | public void OverloadsTest()
100 | {
101 | var ac = new AhoCorasick(new List { "a" });
102 | Assert.That(ac.Search("a").ToList(), Is.EquivalentTo(new WordMatchList { { 0, "a" } }));
103 | Assert.That(ac.Search("b"), Is.Empty);
104 |
105 | ac = new AhoCorasick(CharComparer.OrdinalIgnoreCase, new List { "a", "ab", "bab", "bC", "bca", "c", "caa" });
106 | var m = ac.Search("abCcab").ToList();
107 | var expected = new WordMatchList { { 0, "a" }, { 0, "ab" }, { 1, "bC" }, { 2, "c" }, { 3, "c" }, { 4, "a" }, { 4, "ab" } };
108 | Assert.That(m, Is.EquivalentTo(expected));
109 |
110 | ac = new AhoCorasick();
111 | ac.Add("a");
112 | ac.BuildFail();
113 | Assert.That(ac.Search("a").ToList(), Is.EquivalentTo(new WordMatchList { { 0, "a" } }));
114 | Assert.That(ac.Search("b"), Is.Empty);
115 |
116 | ac = new AhoCorasick(CharComparer.Create(CultureInfo.InvariantCulture, true), "a", "ab", "bab", "bc", "bca", "c", "caa");
117 | m = ac.Search("abccab").ToList();
118 | expected = new WordMatchList { { 0, "a" }, { 0, "ab" }, { 1, "bc" }, { 2, "c" }, { 3, "c" }, { 4, "a" }, { 4, "ab" } };
119 | Assert.That(m, Is.EquivalentTo(expected));
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/AhoCorasick.SqlClr/Contains.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.Data.SqlClient;
4 | using System.Data.SqlTypes;
5 | using Microsoft.SqlServer.Server;
6 | using System.Xml.Linq;
7 | using System.Linq;
8 | using Ganss.Text;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 | using System.Security.Cryptography;
12 | using System.Text;
13 | using System.Globalization;
14 |
15 | public partial class UserDefinedFunctions
16 | {
17 | private static AhoCorasick BuildAhoCorasick(SqlXml xml, SqlString culture)
18 | {
19 | var xe = XElement.Load(xml.CreateReader());
20 | var words = xe.Elements().Select(e => e.FirstAttribute.Value);
21 | var c = culture.Value.Split(':');
22 | var ignoreCase = c.Length > 1 && c[1] == "i";
23 | CharComparer cc;
24 | switch (c[0])
25 | {
26 | case "c":
27 | cc = CharComparer.Create(CultureInfo.CurrentCulture, ignoreCase);
28 | break;
29 | case "n":
30 | cc = CharComparer.Create(CultureInfo.InvariantCulture, ignoreCase);
31 | break;
32 | case "o":
33 | case "":
34 | cc = ignoreCase ? CharComparer.OrdinalIgnoreCase : CharComparer.Ordinal;
35 | break;
36 | default:
37 | cc = CharComparer.Create(CultureInfo.GetCultureInfo(c[0]), ignoreCase);
38 | break;
39 | }
40 | var ac = new AhoCorasick(cc, words);
41 | return ac;
42 | }
43 |
44 | [SqlFunction(FillRowMethodName = "FillRow", TableDefinition = @"""Index"" int, Word nvarchar(MAX)",
45 | IsDeterministic = true, IsPrecise = true, DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None)]
46 | public static IEnumerable ContainsWordsTable(SqlXml xml, SqlString text, SqlString culture)
47 | {
48 | var ac = BuildAhoCorasick(xml, culture);
49 | var matches = ac.Search(text.Value);
50 |
51 | return matches;
52 | }
53 |
54 | [SqlFunction(IsDeterministic = true, IsPrecise = true, DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None)]
55 | public static bool ContainsWords(SqlXml xml, SqlString text, SqlString culture)
56 | {
57 | return ContainsWordsTable(xml, text, culture).Cast().Any();
58 | }
59 |
60 | public static void FillRow(object obj, out int index, out SqlString word)
61 | {
62 | var match = (WordMatch)obj;
63 | index = match.Index;
64 | word = match.Word;
65 | }
66 |
67 | [SqlFunction(IsDeterministic = true, IsPrecise = true, DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None)]
68 | public static string CreateAhoCorasick(SqlXml xml, SqlString culture)
69 | {
70 | var ac = BuildAhoCorasick(xml, culture);
71 | var hash = Hash(xml.Value + culture.Value);
72 | Objects[hash] = ac;
73 | return hash;
74 | }
75 |
76 | [SqlFunction(IsPrecise = true, DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None)]
77 | public static bool DeleteAhoCorasick(SqlString obj)
78 | {
79 | Objects.Remove(obj.Value);
80 | return true;
81 | }
82 |
83 | [SqlFunction(IsDeterministic = true, IsPrecise = true, DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None)]
84 | public static bool ClearAhoCorasick()
85 | {
86 | Objects.Clear();
87 | return true;
88 | }
89 |
90 | [SqlFunction(FillRowMethodName = "FillRow", TableDefinition = @"""Index"" int, Word nvarchar(MAX)", IsDeterministic = true, IsPrecise = true,
91 | DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None)]
92 | public static IEnumerable ContainsWordsTableByObject(SqlString text, SqlString obj)
93 | {
94 | var ac = Objects[obj.Value];
95 | var matches = ac.Search(text.Value);
96 |
97 | return matches;
98 | }
99 |
100 | [SqlFunction(IsDeterministic = true, IsPrecise = true, DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None)]
101 | public static bool ContainsWordsByObject(SqlString text, SqlString obj)
102 | {
103 | return ContainsWordsTableByObject(text, obj).Cast().Any();
104 | }
105 |
106 | [SqlFunction(FillRowMethodName = "FillRow", TableDefinition = @"""Index"" int, Word nvarchar(MAX)", IsDeterministic = true, IsPrecise = true,
107 | DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None)]
108 | public static IEnumerable ContainsWordsBoundedTableByObject(SqlString text, SqlString obj)
109 | {
110 | var ac = Objects[obj.Value];
111 | var t = text.Value;
112 | var matches = ac.Search(t).Cast().Where(m =>
113 | {
114 | var start = m.Index == 0 || !char.IsLetterOrDigit(t[m.Index - 1]);
115 | var end = (m.Index + m.Word.Length) == t.Length || !char.IsLetterOrDigit(t[m.Index + m.Word.Length]);
116 | return start && end;
117 | });
118 |
119 | return matches;
120 | }
121 |
122 | [SqlFunction(IsDeterministic = true, IsPrecise = true, DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None)]
123 | public static bool ContainsWordsBoundedByObject(SqlString text, SqlString obj)
124 | {
125 | return ContainsWordsBoundedTableByObject(text, obj).Cast().Any();
126 | }
127 |
128 | [SqlFunction(FillRowMethodName = "FillRowList", TableDefinition = @"Hash nvarchar(MAX)", IsDeterministic = true, IsPrecise = true,
129 | DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None)]
130 | public static IEnumerable ListAhoCorasick()
131 | {
132 | return Objects.Keys;
133 | }
134 |
135 | public static void FillRowList(object obj, out SqlString word)
136 | {
137 | word = (string)obj;
138 | }
139 |
140 | private static string Hash(string s)
141 | {
142 | return string.Concat(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(s)).Select(b => b.ToString("X2")));
143 | }
144 |
145 | private static readonly Dictionary Objects = new Dictionary();
146 | }
147 |
--------------------------------------------------------------------------------
/AhoCorasick/AhoCorasick.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace Ganss.Text
4 | {
5 | ///
6 | /// Represents a word match.
7 | ///
8 | public struct WordMatch
9 | {
10 | ///
11 | /// Gets or sets the index of the matched word in the searched text string.
12 | ///
13 | ///
14 | /// The index.
15 | ///
16 | public int Index { get; set; }
17 |
18 | ///
19 | /// Gets or sets the matched word.
20 | ///
21 | ///
22 | /// The matched word.
23 | ///
24 | public string Word { get; set; }
25 | }
26 |
27 | ///
28 | /// Implements the Aho-Corasick algorithm.
29 | ///
30 | public class AhoCorasick
31 | {
32 | ///
33 | /// Gets or sets the trie.
34 | ///
35 | ///
36 | /// The trie.
37 | ///
38 | protected Trie Trie { get; set; }
39 |
40 | ///
41 | /// Initializes a new instance of the class.
42 | /// Does not build the failure nodes. Call after adding words before calling .
43 | ///
44 | public AhoCorasick()
45 | {
46 | Trie = new Trie();
47 | }
48 |
49 | ///
50 | /// Initializes a new instance of the class.
51 | ///
52 | /// Does not build the failure nodes. Call after adding words before calling .
53 | /// The comparer used to compare individual characters.
54 | public AhoCorasick(IEqualityComparer comparer)
55 | {
56 | Trie = new Trie(comparer);
57 | }
58 |
59 | ///
60 | /// Initializes a new instance of the class.
61 | ///
62 | /// The words to find.
63 | public AhoCorasick(params string[] words)
64 | : this()
65 | {
66 | Add(words);
67 | }
68 |
69 | ///
70 | /// Initializes a new instance of the class.
71 | ///
72 | /// The words to find.
73 | public AhoCorasick(IEnumerable words)
74 | : this()
75 | {
76 | Add(words);
77 | }
78 |
79 | ///
80 | /// Initializes a new instance of the class.
81 | ///
82 | /// The comparer used to compare individual characters.
83 | /// The words to find.
84 | public AhoCorasick(IEqualityComparer comparer, params string[] words)
85 | : this(comparer)
86 | {
87 | Add(words);
88 | }
89 |
90 | ///
91 | /// Initializes a new instance of the class.
92 | ///
93 | /// The comparer used to compare individual characters.
94 | /// The words to find.
95 | public AhoCorasick(IEqualityComparer comparer, IEnumerable words)
96 | : this(comparer)
97 | {
98 | Add(words);
99 | }
100 |
101 | ///
102 | /// Adds the specified word.
103 | ///
104 | /// Does not build the failure nodes. Call after adding words before calling .
105 | /// The word.
106 | public void Add(string word)
107 | {
108 | Trie.Add(word);
109 | }
110 |
111 | ///
112 | /// Adds the specified words.
113 | ///
114 | /// The words.
115 | public void Add(IEnumerable words)
116 | {
117 | foreach (var word in words)
118 | {
119 | Trie.Add(word);
120 | }
121 |
122 | BuildFail();
123 | }
124 |
125 | ///
126 | /// Builds the failure nodes necessary to perform search.
127 | ///
128 | /// The start node.
129 | public void BuildFail(Trie node = null)
130 | {
131 | node ??= Trie;
132 |
133 | var word = node.Word;
134 | for (int i = 1; i < word.Length && node.Fail == null; i++)
135 | node.Fail = Trie.ExploreFailLink(word, i, word.Length);
136 |
137 | foreach (var subNode in node.Next.Values)
138 | BuildFail(subNode);
139 | }
140 |
141 | ///
142 | /// Searches for words in the specified text.
143 | ///
144 | /// The text.
145 | /// The matched words.
146 | public virtual IEnumerable Search(string text)
147 | {
148 | if (text == null) yield break;
149 |
150 | var current = Trie;
151 |
152 | for (int i = 0; i < text.Length; i++)
153 | {
154 | var c = text[i];
155 |
156 | while (current != null && !current.Next.ContainsKey(c))
157 | current = current.Fail;
158 |
159 | current ??= Trie;
160 |
161 | if (current.Next.TryGetValue(c, out current))
162 | {
163 | var node = current;
164 |
165 | while (node != null)
166 | {
167 | if (node.IsWord)
168 | {
169 | var word = node.Word;
170 | var offset = i + 1 - word.Length;
171 | yield return new WordMatch { Index = offset, Word = word };
172 | }
173 |
174 | node = node.Fail;
175 | }
176 | }
177 | }
178 | }
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/AhoCorasick/CharComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace Ganss.Text
8 | {
9 | class OrdinalCharComparer : CharComparer
10 | {
11 | private readonly bool _ignoreCase;
12 |
13 | public OrdinalCharComparer(bool ignoreCase = false)
14 | {
15 | _ignoreCase = ignoreCase;
16 | }
17 |
18 | public override bool Equals(char x, char y)
19 | {
20 | return _ignoreCase ? ((uint)char.ToUpperInvariant(x)).Equals(((uint)char.ToUpperInvariant(y)))
21 | : ((uint)x).Equals((uint)y);
22 | }
23 |
24 | public override int GetHashCode(char obj)
25 | {
26 | return _ignoreCase ? (int)char.ToUpperInvariant(obj) : (int)obj;
27 | }
28 | }
29 |
30 | #if NET40
31 | class CultureCharComparer : CharComparer
32 | {
33 | private readonly StringComparer _stringComparer;
34 |
35 | public CultureCharComparer(CultureInfo cultureInfo, bool ignoreCase = false)
36 | {
37 | _stringComparer = StringComparer.Create(cultureInfo, ignoreCase);
38 | }
39 |
40 | public override bool Equals(char x, char y)
41 | {
42 | return _stringComparer.Equals(x.ToString(), y.ToString());
43 | }
44 |
45 | public override int GetHashCode(char obj)
46 | {
47 | return _stringComparer.GetHashCode(obj.ToString());
48 | }
49 | }
50 | #else
51 | class CultureCharComparer: CharComparer
52 | {
53 | private readonly CompareInfo _compareInfo;
54 | private readonly bool _ignoreCase;
55 |
56 | public CultureCharComparer(CultureInfo cultureInfo, bool ignoreCase = false)
57 | {
58 | _compareInfo = cultureInfo.CompareInfo;
59 | _ignoreCase = ignoreCase;
60 | }
61 |
62 | public override bool Equals(char x, char y)
63 | {
64 | return _compareInfo.Compare(x.ToString(), y.ToString(), _ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None) == 0;
65 | }
66 |
67 | public override int GetHashCode(char obj)
68 | {
69 | return _compareInfo.GetHashCode(obj.ToString(), _ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
70 | }
71 | }
72 | #endif
73 |
74 | ///
75 | /// Represents a char comparison operation that uses specific case and culture-based or ordinal comparison rules.
76 | ///
77 | public abstract class CharComparer: EqualityComparer
78 | {
79 | private static readonly CharComparer _ordinalIgnoreCase = new OrdinalCharComparer(ignoreCase: true);
80 |
81 | ///
82 | /// Gets a object that performs a case-insensitive ordinal comparison.
83 | ///
84 | ///
85 | /// A object.
86 | ///
87 | public static CharComparer OrdinalIgnoreCase
88 | {
89 | get
90 | {
91 | return _ordinalIgnoreCase;
92 | }
93 | }
94 |
95 | private static readonly CharComparer _ordinal = new OrdinalCharComparer(ignoreCase: false);
96 |
97 | ///
98 | /// Gets a object that performs a case-sensitive ordinal comparison.
99 | ///
100 | ///
101 | /// A object.
102 | ///
103 | public static CharComparer Ordinal
104 | {
105 | get
106 | {
107 | return _ordinal;
108 | }
109 | }
110 |
111 | private static readonly CharComparer _invariantCultureIgnoreCase = new CultureCharComparer(CultureInfo.InvariantCulture, ignoreCase: true);
112 |
113 | ///
114 | /// Gets a object that performs a case-insensitive comparison using the comparison rules of the invariant culture.
115 | ///
116 | ///
117 | /// A object.
118 | ///
119 | public static CharComparer InvariantCultureIgnoreCase
120 | {
121 | get
122 | {
123 | return _invariantCultureIgnoreCase;
124 | }
125 | }
126 |
127 | private static readonly CharComparer _invariantCulture = new CultureCharComparer(CultureInfo.InvariantCulture, ignoreCase: false);
128 |
129 | ///
130 | /// Gets a object that performs a case-sensitive comparison using the comparison rules of the invariant culture.
131 | ///
132 | ///
133 | /// A object.
134 | ///
135 | public static CharComparer InvariantCulture
136 | {
137 | get
138 | {
139 | return _invariantCulture;
140 | }
141 | }
142 |
143 | ///
144 | /// Gets a object that performs a case-sensitive comparison using the comparison rules of the current culture.
145 | ///
146 | ///
147 | /// A object.
148 | ///
149 | public static CharComparer CurrentCulture
150 | {
151 | get
152 | {
153 | return new CultureCharComparer(CultureInfo.CurrentCulture, ignoreCase: false);
154 | }
155 | }
156 |
157 | ///
158 | /// Gets a object that performs a case-insensitive comparison using the comparison rules of the current culture.
159 | ///
160 | ///
161 | /// A object.
162 | ///
163 | public static CharComparer CurrentCultureIgnoreCase
164 | {
165 | get
166 | {
167 | return new CultureCharComparer(CultureInfo.CurrentCulture, ignoreCase: true);
168 | }
169 | }
170 |
171 | ///
172 | /// Creates a object that compares characters according to the rules of a specified culture.
173 | ///
174 | /// A culture whose linguistic rules are used to perform a string comparison.
175 | /// true to specify that comparison operations be case-insensitive; false to specify that comparison operations be case-sensitive.
176 | /// A new object that performs character comparisons according to the comparison rules used by the parameter and the case rule specified by the parameter.
177 | public static CharComparer Create(CultureInfo cultureInfo, bool ignoreCase)
178 | {
179 | return new CultureCharComparer(cultureInfo, ignoreCase);
180 | }
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AhoCorasick
2 |
3 | [](https://www.nuget.org/packages/AhoCorasick)
4 | [](https://ci.appveyor.com/project/mganss/ahocorasick/branch/master)
5 | [](https://coveralls.io/github/mganss/AhoCorasick?branch=master)
6 | [](https://img.shields.io/badge/netstandard-2.0-brightgreen.svg)
7 | [](https://img.shields.io/badge/net-40-brightgreen.svg)
8 |
9 | This is an implementation of the [Aho-Corasick](https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm) string matching algorithm for .NET (netstandard2.0 and net40) and SQL Server (SQL CLR). Mostly ported from [xudejian/aho-corasick](https://github.com/xudejian/aho-corasick) in CoffeeScript.
10 |
11 | ## Usage
12 |
13 | ```C#
14 | var ac = new AhoCorasick("a", "ab", "bab", "bc", "bca", "c", "caa");
15 | var results = ac.Search("abccab").ToList();
16 |
17 | Assert.AreEqual(0, results[0].Index); // index into the searched text
18 | Assert.AreEqual("a", results[0].Word); // matched word
19 | // ...
20 | ```
21 |
22 | or
23 |
24 | ```C#
25 | var results = "abccab".Contains("a", "ab", "bab", "bc", "bca", "c", "caa").ToList();
26 | ```
27 |
28 | ### Custom char comparison
29 |
30 | You can optionally supply an `IEqualityComparer` to perform custom char comparisons when searching for substrings. Several implementations with comparers that mirror `StringComparer` are included.
31 |
32 | ```C#
33 | var results = "AbCcab".Contains(CharComparer.OrdinalIgnoreCase, "a", "ab", "c").ToList();
34 | ```
35 |
36 | ## SQL CLR Functions
37 |
38 | There are also several SQL CLR user defined functions that can be used to perform fast substring matching
39 | in Microsoft SQL Server. To use this:
40 |
41 | 1. Make sure you have [enabled CLR integration](https://msdn.microsoft.com/en-us/library/ms131048.aspx)
42 | 2. Execute [AhoCorasick.SqlClr_Create.sql](AhoCorasick.SqlClr/dist/AhoCorasick.SqlClr_Create.sql)
43 |
44 | For one-off queries, you can use the functions that rebuild the trie on each query, e.g.
45 |
46 | ```SQL
47 | select top(100) * from Posts P
48 | where dbo.ContainsWords((select Word from Words for xml raw, root('root')), P.Body, 'o') = 1
49 | ```
50 |
51 | The words to match are always supplied as XML where the values are taken from the first attribute of all elements directly beneath the root node. Be careful to select the word column as the only or first column otherwise you'll end up matching the wrong words. The XML in the example above looks like this:
52 |
53 | ```XML
54 |
55 |
56 |
57 |
58 | ...
59 |
60 | ```
61 |
62 | [Here's more](https://www.simple-talk.com/sql/learn-sql-server/using-the-for-xml-clause-to-return-query-results-as-xml/) about FOR XML.
63 |
64 | The last parameter in the function indicates the culture to use since there is no way to use SQL Server collations in SQL CLR code. Values can be:
65 |
66 | |Value|Character comparison|
67 | |-----|--------------------|
68 | |c|Current Culture|
69 | |n|Invariant Culture|
70 | |o or Empty|Ordinal|
71 | |Culture name, e.g. "de-de"|Specific [.NET Culture](https://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.name.aspx)|
72 |
73 | The culture identifier can be suffixed by `:i` indicating case-insensitive matching.
74 |
75 | ### Static objects
76 |
77 | The function in the example above has the problem that the trie is rebuilt for each query even though the input always stays the same. To overcome this problem, there are a number of functions to manage the creation and destruction of static objects whose handles can be saved in SQL variables. Example:
78 |
79 | ```SQL
80 | declare @ac nvarchar(32);
81 | set @ac = dbo.CreateAhoCorasick((select Word from Words for xml raw, root('root')), 'en-us:i');
82 | select * from Posts P
83 | where dbo.ContainsWordsByObject(P.Body, @ac) = 1;
84 | ```
85 |
86 | This is a lot faster than the first example because the trie is created only once and then reused for each row in the query. The handle (@ac) is a hash value generated from the words to match and the culture. The corresponding object is saved in a static dictionary. You can list the currently active objects using `dbo.ListAhoCorasick()`, remove all objects using `dbo.ClearAhoCorasick()` or remove only one object using `dbo.DeleteAhoCorasick(@ac)`.
87 |
88 | ### Getting all matches
89 |
90 | The examples above only checked if the words occurred in the queried texts. If you want to get the matched words and the indexes where they occur in the queried texts you can use the supplied table-valued functions. For example:
91 |
92 | ```SQL
93 | declare @ac nvarchar(32);
94 | set @ac = dbo.CreateAhoCorasick((select Word from Words for xml raw, root('root')), 'o');
95 | select top(100) * from Posts P
96 | cross apply dbo.ContainsWordsTableByObject(P.Body, @ac) W
97 | ```
98 |
99 | This will return a table such as this:
100 |
101 | |ID |Body |Index |Word |
102 | |---|---|---|---|
103 | |1 |What factors related...|5|factor|
104 | |1 |What factors related...|6|actor|
105 | |1 |What factors related...|5|factors|
106 | |...|
107 |
108 | ### Word boundaries
109 |
110 | There are also functions that return only matches occuring at word boundaries: `dbo.ContainsWordsBoundedByObject()` and `dbo.ContainsWordsBoundedTableByObject()`. Word boundaries here are the same as [`\b` in regexes](http://www.regular-expressions.info/wordboundaries.html), i.e. matches will occur as if words were specified as `\bword\b`.
111 |
112 | ### Forcing parallelism
113 |
114 | Although these kinds of queries lend themselves very well to parallel execution, SQL Server tends to overestimate the cost of parallel queries and builds non-parallel plans most of the time where user defined functions are involved. You can force a parallel plan by using a trace flag (more about this [here](http://sqlblog.com/blogs/paul_white/archive/2011/12/23/forcing-a-parallel-query-execution-plan.aspx)):
115 |
116 | ```SQL
117 | declare @ac nvarchar(32);
118 | set @ac = dbo.CreateAhoCorasick((select Word from Words for xml raw, root('root')), 'en-us:i');
119 | select * from Posts P
120 | where dbo.ContainsWordsBoundedByObject(P.Body, @ac) = 1
121 | OPTION (RECOMPILE, QUERYTRACEON 8649)
122 | ```
123 |
124 | Parallel operators are identified by a yellow badge with two arrows in the query plan.
125 |
126 | ### Performance
127 |
128 | Here's a benchmark searching for ~5000 words (average length 7) in ~250,000 texts (average length ~900):
129 |
130 | |SQL|AhoCorasick|
131 | |---|-----------|
132 | |560s|7s|
133 |
134 | The SQL query used was this:
135 |
136 | ```SQL
137 | select * from Posts P
138 | where exists (select * from Words W where CHARINDEX(W.Word, P.Text) > 0)
139 | ```
140 |
141 | #### But I can simply use full-text search
142 |
143 | No. The [CONTAINS](https://msdn.microsoft.com/en-us/library/ms187787.aspx) predicate can only search for a single literal or variable at a time. You can't use it in a join or subquery to search for a column value of a table in the query, i.e. this won't work:
144 |
145 | ```SQL
146 | select * from Posts P
147 | where exists (select * from Words W where CONTAINS(P.Text, W.Word))
148 | ```
149 |
150 | If you know of a way to make this work using FTS (perhaps using a cursor?) let me know.
151 |
--------------------------------------------------------------------------------
/AhoCorasick.SqlClr/dist/AhoCorasick.SqlClr_Create.sql:
--------------------------------------------------------------------------------
1 | PRINT N'Creating [AhoCorasick.SqlClr]...';
2 |
3 |
4 | GO
5 | CREATE ASSEMBLY [AhoCorasick.SqlClr]
6 | AUTHORIZATION [dbo]
7 | FROM 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C010300F0CEA95D0000000000000000E00022200B013000002E00000006000000000000F64D000000200000006000000000001000200000000200000400000000000000040000000000000000A000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000A44D00004F00000000600000D002000000000000000000000000000000000000008000000C0000006C4C00001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E74657874000000FC2D000000200000002E000000020000000000000000000000000000200000602E72737263000000D0020000006000000004000000300000000000000000000000000000400000402E72656C6F6300000C0000000080000000020000003400000000000000000000000000004000004200000000000000000000000000000000D84D0000000000004800000002000500C8290000A4220000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013300500EB00000001000011026F0F00000A281000000A6F1100000A7E11000004252D17267E10000004FE0640000006731200000A258011000004280100002B0A0F01281400000A178D2000000125161F3A9D6F1500000A0B078E6917310F07179A7201000070281600000A2B01160C07169A130411042C6711047205000070281600000A2D2B11047209000070281600000A2D2B1104720D000070281600000A2D2B11042C391104281700000A2C1E2B2E281800000A08282D0000060D2B2F281900000A08282D0000060D2B21082D0728280000062B0528270000060D2B0F07169A281A00000A08282D0000060D0906731C0000062A52020428010000060F01281400000A6F200000062A4E0203042802000006280200002B280300002B2A13300200230000000200001102A5030000020A0312002811000006540412002813000006281D00000A81080000012A00133003002E00000003000011020328010000060A026F1E00000A0F01281400000A281F00000A280E0000060B7E0100000407066F2000000A072A527E010000040F00281400000A6F2100000A26172A327E010000046F2200000A172A7A7E010000040F01281400000A6F2300000A0F00281400000A6F200000062A4A02032808000006280200002B280300002B2A000013300300460000000400001173420000060A7E010000040F01281400000A6F2300000A060F00281400000A7D13000004067B130000046F20000006280200002B06FE0643000006732400000A280400002B2A4A0203280A000006280200002B280300002B2A2E7E010000046F2600000A2A4A03027421000001281D00000A81080000012AFE282700000A282800000A026F2900000A6F2A00000A7E12000004252D17267E10000004FE0641000006732B00000A258012000004280500002B282C00000A2A1E02282D00000A2A2E732E00000A80010000042A1E027B020000042A2202037D020000042A1E027B030000042A2202037D030000042A1E027B040000042A2202037D040000042A4A02282D00000A02733A00000628160000062A4E02282D00000A0203733B00000628160000062A3A0228170000060203281E0000062A3E020328180000060204281E0000062A3A022815000006036F3C000006262A1B3002003900000005000011036F2F00000A0A2B14066F3000000A0B022815000006076F3C00000626066F0800000A2DE4DE0A062C06066F0700000ADC0214281F0000062A00000001100000020007002027000A000000001B300400810000000600001103252D07260228150000061001036F380000060A170B2B1C0302281500000606076F3100000A6F3D0000066F350000060717580B07066F1700000A2F08036F340000062CD3036F300000066F3200000A6F3300000A0C2B0F1202283400000A0D0209281F0000061202283500000A2DE8DE0E1202FE160C00001B6F0700000ADC2A00000001100000020056001C72000E000000005A1FFE734400000625027D1900000425037D180000042A3A02282E00000602037D050000042A0000133002002800000007000011027B050000042D0B030A120004283600000A2A03283700000A0A120004283700000A283600000A2A46027B050000042D02032A03283700000A2A5202282E000006020304283800000A7D060000042A6A027B060000040F01283900000A0F02283900000A6F3A00000A2A4E027B060000040F01283900000A6F3B00000A2A1A7E070000042A1A7E080000042A1A7E090000042A1A7E0A0000042A32281800000A1673240000062A32281800000A1773240000062A22020373240000062A1E02283C00000A2ADE17732100000680070000041673210000068008000004281900000A1773240000068009000004281900000A167324000006800A0000042A1E027B0B0000042A2202037D0B0000042A1E027B0C0000042A2202037D0C0000042A1E027B0D0000042A2202037D0D0000042A1E027B0E0000042A2202037D0E0000042A1E027B0F0000042A2202037D0F0000042A7602282D00000A027211000070283900000602733D00000A28310000062A7A02282D00000A02721100007028390000060203733E00000A28310000062A0013300600750000000800001103166F3F00000A0A0228300000060612016F4000000A2D3D022830000006060228300000066F4100000A733B00000625026F37000006250228380000061200283900000A281F00000A6F39000006250B6F4200000A036F1700000A17310E0703176F3100000A6F3C0000062A07176F33000006072A000000133003003300000009000011020A030B160C2B2007086F3F00000A0D066F300000060912006F4000000A26062D02142A0817580C08076F1700000A32D7062A2E733F00000680100000042A32036F4300000A6F4400000A2A360F017213000070284500000A2A000013300400770000000A0000110F0128110000062C1E027B130000040F01281100000617596F3F00000A284600000A16FE012B01170F0128110000060F0128130000066F1700000A58027B130000046F1700000A2E29027B130000040F0128110000060F0128130000066F1700000A586F3F00000A284600000A16FE012B01170A065F2A7A02282D00000A02037D1400000402284700000A6F4800000A7D160000042A062A13300300660100000B000011027B140000040A027B190000040B062C0906173BFD000000162A02157D14000004027B170000042D02162A020728150000067D1A00000402167D1B000004380B010000027B17000004027B1B0000046F3F00000A0C2B1102027B1A0000046F340000067D1A000004027B1A0000042C13027B1A0000046F30000006086F4900000A2CD4027B1A0000042D0C020728150000067D1A000004027B1A0000046F3000000608027C1A0000046F4000000A398900000002027B1A0000047D1C0000042B6C027B1C0000046F320000062C4E027B1C0000046F380000060D027B1B0000041758096F1700000A591304021205FE1503000002120511042812000006120509281400000611057D1500000402177D14000004172A02157D1400000402027B1C0000046F340000067D1C000004027B1C0000042D8C02147D1C000004027B1B000004130602110617587D1B000004027B1B000004027B170000046F1700000A3FDFFEFFFF162A1E027B150000042A1A734A00000A7A32027B150000048C030000022A000013300200480000000C000011027B140000041FFE331D027B16000004284700000A6F4800000A330B02167D14000004020A2B131673440000060A06027B190000047D1900000406027B180000047D17000004062A1E02284A0000062A42534A4201000100000000000C00000076342E302E33303331390000000005006C000000400D0000237E0000AC0D00003C0B000023537472696E677300000000E81800001C0000002355530004190000100000002347554944000000141900009009000023426C6F620000000000000002000001571FA20B090A000000FA013300160000010000002A0000000B0000001C0000004B0000003E000000050000004A00000003000000310000000C000000050000001000000018000000070000000C000000010000000500000003000000050000000000B90501000000000006003204FD0706007904FD070600F103D6070F001D08000006002209F8050600C40025010A00DB052C080A00D9042C080600780025010A001D0417070A00290217070A002302170706009B0266080600D603FD070600BD00F8050E00880971060600B302F80506008600250106006504F80506009A0025011B00220600005700BE0700000600A702F80506004507660806000504D6070600C706F805060059060D060600870025011200A506D0050E00AF06710616009C02810606009306F8050600E504F8051B00320600000600F2000F0B0600D004C00A0600FF050F0B0600A800F8050E00CB03710606009704F80506007401BF0406004006F8050000000003010000000001000100010010007908000015000100010009011000FD04CC0A450002001100010010006C05CC0A15000400150000001000FA06CC0A1C000500210000001000E606CC0A1C0006002400810010000107CC0A0E0007002700010010008302CC0A15000B0030000321100021010000150010003E00030110003B00000015001300420003011000D100000015001400440031009808420201000C024B02010084014E020100B20151022100920355022100D606580231007F035C02310094055C02310030035C023100E4025C020100F601600201009A0155020100C80151020100DE015102010084014E023600FF006902160001006D021600230076020600DF0A4E020100C0034B020100870A7E02010054014B020100DC0A4E020600D70A4E020600550882020100AF0051020100DF004B020100E70051025020000000009100220586020100472100000000960088028F0203005C21000000009600E9079A0206007021000000009600E10AA4020900A0210000000096003305AE020C00DA210000000096004505B6020E00EF210000000096005705BC020F00FC21000000009600F808C0020F001B220000000096001309C90211003022000000009600D608C00213008222000000009600B908C902150095220000000096006805D1021700A122000000009600990AD6021700B4220000000091000E05DE021900F422000000008618C90706001A00FC22000000009118CF07E3021A000823000000008608E90A9F001A001023000000008608F30A01001A00192300000000860838028E001B0021230000000086084102E7021B002A230000000084087602EC021C0032230000000084087F02F1021C003B23000000008618C90706001D004E23000000008618C907F7021D006223000000008618C90700031E006223000000008618C90706031F007123000000008618C9070F0320007123000000008618C9071A03220081230000000086008001E70224009023000000008600800106032500E823000000008600AF05F1022600882400000000C601F604280327009F24000000008618C90732032800B02400000000C6005F0837032900E42400000000C60065023D032B00F624000000008618C90742032C000B2500000000C6005F0837032E00262500000000C60065023D0330003A25000000009608690349033100412500000000960888054903310048250000000096081103490331004F25000000009608CF02490331005625000000009608F6024903310063250000000096084C03490331007025000000009600B9034E0331007925000000008418C907060033008125000000009118CF07E3023300B925000000008608A50A56033300C125000000008608AE0A60033300CA250000000086084A0210003400D225000000008608550232033400DB250000000086089D05EC023500E325000000008608A605F1023500EC250000000086089109EC023600F4250000000086089C09F1023600FD2500000000860838028E00370005260000000081084102E70237000E26000000008618C907060038002C26000000008618C907F70238004C2600000000C60180016B033900D02600000000C60178056B033A000F27000000009118CF07E3023B00F422000000008618C90706003B001B270000000083000A0071033B0028270000000083002D0077033C00F422000000008618C90706003D00382700000000830050007C033D00BB27000000008618C90701003E00DA2700000000E1019E0306003F00DC2700000000E101B70A10003F004E2900000000E109130A82033F00562900000000E101300906003F005D2900000000E1095C0A20003F006C2900000000E101510787033F00C02900000000E1019C0734003F0000000100E20500000200090300000100E20500000200DC0A00000300090300000100E20500000200DC0A000003000903000001001E0502000200FD0A02000300600200000100E205000002000903000001001E0500000100DC0A000002001E0500000100DC0A000002001E0500000100DC0A000002001E0500000100DC0A000002001E05000001001E0502000200600200000100B00800000100B20400000100B20400000100B204000001000E0700000100F70700000100F707000001000E0700000200F707000001000E0700000200F70700000100600200000100F70710100100710200000100DC0A10100100930300000100010B000002003A0B000001001E0500000100650610100200930300000100010B000002003A0B000001001E0500000100650600000200930300000100B20400000100B20400000100B20400000100B20400000100B204000001000E0700000100600200000100600200000100BD04000001001F01000001000B0600000100C0030B000A000B0035000B0006000B005D000B0061000900C90701001100C90706001900C9070A005100C90706007100C90706009900C9070600B900B1030600C100B70A10000C007B0A1B00C1004F090600C1007B0A20001400BB072B006900BB073400C900C9070600390098064D0081007B015200F100A00859002400C9076A00F9002909700041009C048E000901710992000901300B9900090113059F00D900F602A300D900CF02A300D9005606A800F900940AAE00F9002C0BBF0041005509CF0039009C048E000901B208DB002C00EF05E9002C00B804F1002C008D0606002C00E605F7003400C9076A00F900BD020B012C00A90822011901B9032E012101F6003401210141083A012901070540013C00C9076A000901B20853012900C90706002C00C90706004400BB072B004C007B0A1B000901EC047F0154004A088C015C00BB079F0164007B0AB2016400B70A100031015F08BB0101017709C001D100B903C5010101E3048E00D1005F08CD01D1006502D3011C00C90706005400C90706005400C907D80109018E08E8015400A604ED015400BA06F6015400EF05E90081005204070239019C048E004101E3040D02010161091602490169011B02490140019F005400030BF1005101C9070600120099003B020200A10040020200B50040022E000B00B9032E001300C2032E001B00E10340002300EA0341002B008A0960002300800561002B008A0981002B008A09A00023008005C0002300C806E0002300800500012300EA0320012300800523012B008A0940012300EA0343012B008A0960012300800561012B008A0963012B008A0980012300FD0781012B008A09A1012B008A09C1012B008A09E1012B008A0920022B008A0940022B008A0960022B008A0980022B008A09A0022B008A09C0022B008A09C40333008A09240433008A0900062B008A0920062B008A0940062B008A0960062B008A0980062B008A09A0062B008A09C0062B008A09E0062B008A0900072B008A0920072B008A09800873008A09A00873008A09E00873008A09000973008A09200973008A09400973008A09600973008A093F00CA00D500FE005C017101B701E201FF01120221022D0203000100040003000700040008000A000B000F000000F70A900300005B02940300008302980300006D039D0300008C059D03000015039D030000D3029D030000FA029D03000050039D030000BB0AA20300005902AC030000B40598030000A009980300005B0294030000A709B0030000EC09B503020011000300010012000300020013000500010014000500020015000700010016000700020027000900020028000B00020029000D0002002A000F0002002B00110002002C001300020030001500010031001500020032001700010033001700020034001900010035001900020036001B00010037001B00020038001D00010039001D00020047001F000200490021000B008A000F000B008C0011000B008E0013000B00900015000B00920017000B00940019000B0096001B001400240039006200E1000301470165016B0184019701AA0104800000000000000000000000000000000032070000040000000000000000000000320218010000000004000000000000000000000032020C010000000004000000000000000000000032027106000000000400000000000000000000003202D005000000000400000000000000000000003202C30200000000090002000A0002000B000400270088003700BA003900BA004B00BA0027004E010000003C3E395F5F305F30003C4275696C6441686F436F72617369636B3E625F5F305F30003C3E395F5F31335F30003C486173683E625F5F31335F30003C3E635F5F446973706C6179436C617373395F30003C436F6E7461696E73576F726473426F756E6465645461626C6542794F626A6563743E625F5F300049456E756D657261626C6560310049457175616C697479436F6D706172657260310049456E756D657261746F7260310055496E743332003C63757272656E743E355F5F320046756E6360320044696374696F6E6172796032003C5365617263683E645F5F3133003C693E355F5F33003C6E6F64653E355F5F34004D4435006765745F55544638003C3E39003C4D6F64756C653E0053797374656D2E44617461006D73636F726C6962003C3E630053797374656D2E436F6C6C656374696F6E732E47656E65726963006765745F4D616E616765645468726561644964003C3E6C5F5F696E697469616C5468726561644964006765745F43757272656E74546872656164004C6F616400416464003C576F72643E6B5F5F4261636B696E674669656C64003C4973576F72643E6B5F5F4261636B696E674669656C64003C547269653E6B5F5F4261636B696E674669656C64003C4661696C3E6B5F5F4261636B696E674669656C64003C506172656E743E6B5F5F4261636B696E674669656C64003C4E6578743E6B5F5F4261636B696E674669656C64003C496E6465783E6B5F5F4261636B696E674669656C640053797374656D446174614163636573734B696E64006765745F576F7264007365745F576F7264006765745F4973576F7264007365745F4973576F726400776F72640047657448617368436F6465006E6F6465006765745F54726965007365745F5472696500436F6E7461696E73576F7264735461626C650049456E756D657261626C650049446973706F7361626C650056616C7565547970650057686572650053797374656D2E436F7265006765745F496E76617269616E7443756C74757265005F696E76617269616E7443756C74757265006765745F43757272656E7443756C747572650063756C74757265006765745F496E76617269616E7443756C7475726549676E6F726543617365005F696E76617269616E7443756C7475726549676E6F726543617365006765745F43757272656E7443756C7475726549676E6F726543617365006765745F4F7264696E616C49676E6F726543617365005F6F7264696E616C49676E6F726543617365005F69676E6F7265436173650053797374656D2E49446973706F7361626C652E446973706F736500437265617465003C3E315F5F7374617465005841747472696275746500436F6D70696C657247656E6572617465644174747269627574650044656275676761626C6541747472696275746500446562756767657248696464656E4174747269627574650053716C46756E6374696F6E41747472696275746500436F6D70696C6174696F6E52656C61786174696F6E73417474726962757465006765745F466972737441747472696275746500506172616D41727261794174747269627574650052756E74696D65436F6D7061746962696C6974794174747269627574650042797465006765745F56616C75650054727947657456616C75650076616C75650052656D6F76650053797374656D2E546872656164696E6700456E636F64696E670053716C537472696E6700546F537472696E6700537562737472696E670053656172636800576F72644D6174636800436F6D7075746548617368006765745F4C656E677468006F626A004275696C6441686F436F72617369636B0043726561746541686F436F72617369636B0044656C65746541686F436F72617369636B00436C65617241686F436F72617369636B004C69737441686F436F72617369636B004578706C6F72654661696C4C696E6B006765745F4F7264696E616C005F6F7264696E616C006765745F4661696C007365745F4661696C004275696C644661696C0041686F436F72617369636B2E53716C436C722E646C6C0053797374656D2E586D6C0053716C586D6C00786D6C006765745F4974656D007365745F4974656D0053797374656D0048617368416C676F726974686D0053797374656D2E476C6F62616C697A6174696F6E0056616C7565436F6C6C656374696F6E004B6579436F6C6C656374696F6E004E6F74537570706F72746564457863657074696F6E0047657443756C74757265496E666F0063756C74757265496E666F0053797374656D2E586D6C2E4C696E710053797374656D2E4C696E7100436C65617200436861720043726561746552656164657200586D6C5265616465720058436F6E7461696E6572006765745F436F6D706172657200537472696E67436F6D7061726572005F737472696E67436F6D70617265720043756C7475726543686172436F6D7061726572004F7264696E616C43686172436F6D706172657200636F6D7061726572004D6963726F736F66742E53716C5365727665722E5365727665720041686F436F72617369636B2E53716C436C720049456E756D657261746F720053797374656D2E436F6C6C656374696F6E732E47656E657269632E49456E756D657261626C653C47616E73732E546578742E576F72644D617463683E2E476574456E756D657261746F720053797374656D2E436F6C6C656374696F6E732E49456E756D657261626C652E476574456E756D657261746F72002E63746F72002E6363746F720053797374656D2E446961676E6F737469637300436F6E7461696E73576F72647300776F7264730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F6465730053797374656D2E446174612E53716C5479706573004765744279746573006765745F56616C756573003C3E345F5F7468697300457175616C730053797374656D2E436F6C6C656374696F6E730055736572446566696E656446756E6374696F6E73006765745F4368617273004F626A6563747300456C656D656E7473006765745F4B65797300436F6E63617400436F6E7461696E73576F726473426F756E64656442794F626A65637400436F6E7461696E73576F726473426F756E6465645461626C6542794F626A65637400436F6E7461696E73576F7264735461626C6542794F626A65637400436F6E7461696E73576F72647342794F626A6563740053656C6563740053797374656D2E436F6C6C656374696F6E732E49456E756D657261746F722E5265736574006F705F496D706C696369740049734C65747465724F7244696769740053706C697400546F5570706572496E76617269616E740058456C656D656E74006765745F506172656E74007365745F506172656E740053797374656D2E436F6C6C656374696F6E732E47656E657269632E49456E756D657261746F723C47616E73732E546578742E576F72644D617463683E2E43757272656E740053797374656D2E436F6C6C656374696F6E732E49456E756D657261746F722E43757272656E740053797374656D2E436F6C6C656374696F6E732E47656E657269632E49456E756D657261746F723C47616E73732E546578742E576F72644D617463683E2E6765745F43757272656E740053797374656D2E436F6C6C656374696F6E732E49456E756D657261746F722E6765745F43757272656E74003C3E325F5F63757272656E7400436173740046696C6C526F774C697374006765745F4E657874007365745F4E657874004D6F76654E6578740053797374656D2E546578740047616E73732E54657874003C3E335F5F746578740046696C6C526F77006765745F496E646578007365745F496E64657800696E64657800436F6E7461696E734B65790053797374656D2E53656375726974792E43727970746F67726170687900416E79006F705F457175616C69747900000369000003630000036E0000036F000001000558003200000000002E94443AC555AD49A39E1204C637A3F600042001010803200001052001011111032000020615125101110C04200013000320001C0615122501110C08200015125101130004200012610515127101030D0705151225010E1D0E02121C0E0420001275060001124112750820001512250112410715123D0212410E052002011C1817100202151225011E01151225011E0015123D021E001E01050A0212410E0320000E0620011D0E1D03050002020E0E03200008040000126D050001126D0E0B100101151225011E001235040A01110C0A10010102151225011E00040701110C05000111210E05070212100E0500020E0E0E07151219020E121007200201130013010520010213000620011301130004070112280715123D02110C0216100102151225011E00151225011E0015123D021E00020B200015128089021300130105000012808D0500001280910520011D050E0620011D051D050615123D02050E040A02050E0800010E151225010E080702151251010E0E05151225010E05151251010E0D07040E081511590203122012200420010E0807151219020312200A2000151255021300130107151255020312200A200015115902130013010715115902031220042000130103070109042001020904000103030700021269126D02052002020E0E042001080E09200101151249011300050702031220042001030808200202130010130108200015124901130007070412200E080305200012809D0420010E0E0307010204000102030500001280A50B0707081210030E08110C08040701122C08B77A5C561934E089040000000001000806151219020E121002060802060E03061220020602030612690306121C08061512190203122003061224080615123D0212410E070615123D02050E0306110C030612100800021210121D11210A00031235121D1121112109000302121D11211121090003011C10081011210700020E121D11210500010211210300000208000212351121112107000202112111210400001235070002011C1011210400010E0E03000001042001010E0420001220052001011220082001011512490103052001011D0E08200101151225010E0A20020115124901031D0E0D2002011512490103151225010E09200115122501110C0E0420010102052002020303042001080306200201126D02040000121C070002121C126D02092000151219020312200A2001011512190203122005200112200E0520010E12410420010E0505200102110C042000110C08200015125101110C032800080328000E0428001220040800121C0928001512190203122003280002042800110C0328001C0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F777301080100020000000000819401000600540E1146696C6C526F774D6574686F644E616D650746696C6C526F77540E0F5461626C65446566696E6974696F6E1F22496E6465782220696E742C20576F7264206E76617263686172284D41582954020F497344657465726D696E697374696301540209497350726563697365015455794D6963726F736F66742E53716C5365727665722E5365727665722E446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038390A446174614163636573730000000054557F4D6963726F736F66742E53716C5365727665722E5365727665722E53797374656D446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038391053797374656D446174614163636573730000000081460100040054020F497344657465726D696E697374696301540209497350726563697365015455794D6963726F736F66742E53716C5365727665722E5365727665722E446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038390A446174614163636573730000000054557F4D6963726F736F66742E53716C5365727665722E5365727665722E53797374656D446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038391053797374656D4461746141636365737300000000813301000300540209497350726563697365015455794D6963726F736F66742E53716C5365727665722E5365727665722E446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038390A446174614163636573730000000054557F4D6963726F736F66742E53716C5365727665722E5365727665722E53797374656D446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038391053797374656D4461746141636365737300000000818B01000600540E1146696C6C526F774D6574686F644E616D650B46696C6C526F774C697374540E0F5461626C65446566696E6974696F6E1248617368206E76617263686172284D41582954020F497344657465726D696E697374696301540209497350726563697365015455794D6963726F736F66742E53716C5365727665722E5365727665722E446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038390A446174614163636573730000000054557F4D6963726F736F66742E53716C5365727665722E5365727665722E53797374656D446174614163636573734B696E642C2053797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D623737613563353631393334653038391053797374656D446174614163636573730000000004010000000000000000F0CEA95D00000000020000001C010000884C0000882E000052534453F008FDC110632F41A346158C5BAC73A901000000463A5C50726F6A656374735C41686F436F72617369636B5C41686F436F72617369636B2E53716C436C725C6F626A5C52656C656173655C41686F436F72617369636B2E53716C436C722E706462000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CC4D00000000000000000000E64D0000002000000000000000000000000000000000000000000000D84D0000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF25002000100000000000000000000000000000000000000100100000001800008000000000000000000000000000000100010000003000008000000000000000000000000000000100000000004800000058600000740200000000000000000000740234000000560053005F00560045005200530049004F004E005F0049004E0046004F0000000000BD04EFFE00000100000000000000000000000000000000003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073006C006100740069006F006E00000000000000B004D4010000010053007400720069006E006700460069006C00650049006E0066006F000000B001000001003000300030003000300034006200300000002C0002000100460069006C0065004400650073006300720069007000740069006F006E000000000020000000300008000100460069006C006500560065007200730069006F006E000000000030002E0030002E0030002E00300000004E001700010049006E007400650072006E0061006C004E0061006D0065000000410068006F0043006F00720061007300690063006B002E00530071006C0043006C0072002E0064006C006C00000000002800020001004C006500670061006C0043006F0070007900720069006700680074000000200000005600170001004F0072006900670069006E0061006C00460069006C0065006E0061006D0065000000410068006F0043006F00720061007300690063006B002E00530071006C0043006C0072002E0064006C006C0000000000340008000100500072006F006400750063007400560065007200730069006F006E00000030002E0030002E0030002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000030002E0030002E0030002E00300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000C000000F83D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
8 |
9 |
10 | GO
11 | ALTER ASSEMBLY [AhoCorasick.SqlClr]
12 | DROP FILE ALL
13 | ADD FILE FROM 0x4D6963726F736F667420432F432B2B204D534620372E30300D0A1A4453000000000200000200000043000000580100000000000041000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3800000000000000FCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0BCA3101380000000010000000100000000000001A00FFFF04000000FFFF03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BCA3101380000000010000000100000000000001B00FFFF04000000FFFF0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000942E3101F0CEA95D01000000F008FDC110632F41A346158C5BAC73A900000000000000000100000001000000000000000000000000000000DC51330100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BCA310138000000001000000010000000000000FFFFFFFF04000000FFFF030000000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BCA310138000000001000000010000000000000FFFFFFFF04000000FFFF030000000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F862513FC607D311905300C04FA302A1C4454B99E9E6D211903F00C04FA302A10B9D865A1166D311BD2A0000F80849BD0FD02988B8111342878B770E8597AC1620000000000000005831DA5DBC0BD7E636AD6E1CFF79421BA9941E32825FA5F80D54EC566D272D10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F862513FC607D311905300C04FA302A1C4454B99E9E6D211903F00C04FA302A10B9D865A1166D311BD2A0000F80849BD0FD02988B8111342878B770E8597AC162000000000000000C866E29C886E5B99E7829DEC965F77118969E3894E48C739AF2F28EC856B4F19000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F862513FC607D311905300C04FA302A1C4454B99E9E6D211903F00C04FA302A10B9D865A1166D311BD2A0000F80849BD0FD02988B8111342878B770E8597AC162000000000000000FF5852C579171CBF6783F30C8547AE939CD8C8E26E78E2E3DCAF7D2B53EA3A29000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F862513FC607D311905300C04FA302A1C4454B99E9E6D211903F00C04FA302A10B9D865A1166D311BD2A0000F80849BD0FD02988B8111342878B770E8597AC162000000000000000568D54EA04119982A63B8019D731A4FEFE35FB0DF9A8316D14A517E94910BF840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F707000000000000F7070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FEEFFEEF010000009601000000463A5C50726F6A656374735C41686F436F72617369636B5C41686F436F72617369636B2E53716C436C725C436F6E7461696E732E63730000663A5C70726F6A656374735C61686F636F72617369636B5C61686F636F72617369636B2E73716C636C725C636F6E7461696E732E637300463A5C50726F6A656374735C41686F436F72617369636B5C41686F436F72617369636B5C41686F436F72617369636B2E637300663A5C70726F6A656374735C61686F636F72617369636B5C61686F636F72617369636B5C61686F636F72617369636B2E637300463A5C50726F6A656374735C41686F436F72617369636B5C41686F436F72617369636B5C43686172436F6D70617265722E637300663A5C70726F6A656374735C61686F636F72617369636B5C61686F636F72617369636B5C63686172636F6D70617265722E637300463A5C50726F6A656374735C41686F436F72617369636B5C41686F436F72617369636B5C547269652E637300663A5C70726F6A656374735C61686F636F72617369636B5C61686F636F72617369636B5C747269652E63730011000000000000000A0100000100000039000000380000003E0100006A010000D600000000000000000000000000000000000000A300000070000000000000000000000000000000090000000000000000000000000000000000000000001BE2300104010000FD5F0D08C285D5010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000006000000010000001E00000000000000A3000000280000001BE230016964F98D680000007000000038000000A30000006500000000000000000000000A010000280000001BE23001F6CD6D9E68000000D6000000380000000A01000065000000000000000000000039000000280000001BE23001A30435EC680000000100000038000000390000006500000000000000000000006A010000280000001BE23001A388BC5A680000003E010000380000006A010000650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000003A002A11000000003802000000000000EB0000000000000000000000010000060000000001000000004275696C6441686F436F72617369636B000000160003110400000004020000EB00000000000000010000000A0024115553797374656D00120024115553797374656D2E44617461000000001A0024115553797374656D2E446174612E53716C436C69656E7400001A0024115553797374656D2E446174612E53716C54797065730000001E002411554D6963726F736F66742E53716C5365727665722E53657276657200160024115553797374656D2E586D6C2E4C696E7100000000120024115553797374656D2E4C696E71000000000E0024115547616E73732E5465787400160024115553797374656D2E436F6C6C656374696F6E73001E0024115553797374656D2E436F6C6C656374696F6E732E47656E6572696300220024115553797374656D2E53656375726974792E43727970746F677261706879000000120024115553797374656D2E54657874000000001A0024115553797374656D2E476C6F62616C697A6174696F6E0000001A00201100000000010000110000000000000000776F7264730000001600201101000000010000110000000000000000630000001E0020110200000001000011000000000000000069676E6F7265436173650000160020110300000001000011000000000000000063630000020006002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040000000C00000001000D00020006003A002A1100000000A80200000000000014000000000000000000000002000006EB0000000100000000436F6E7461696E73576F7264735461626C65002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000010000060200060036002A1100000000140300000000000013000000000000000000000003000006FF0000000100000000436F6E7461696E73576F72647300002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000010000060200060032002A1100000000B4030000000000002300000000000000000000000400000612010000010000000046696C6C526F77000000001600031118030000800300002300000012010000010000001A002011000000000200001100000000000000006D61746368000000020006002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000001000006020006003A002A110000000074040000000000002E00000000000000000000000500000635010000010000000043726561746541686F436F72617369636B000016000311B8030000400400002E00000035010000010000001600201100000000030000110000000000000000616300001A002011010000000300001100000000000000006861736800000000020006002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000001000006020006003A002A1100000000E4040000000000001400000000000000000000000600000663010000010000000044656C65746541686F436F72617369636B00002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000001000006020006003A002A110000000054050000000000000C000000000000000000000007000006770100000100000000436C65617241686F436F72617369636B0000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000010000060200060042002A1100000000CC050000000000001E000000000000000000000008000006830100000100000000436F6E7461696E73576F7264735461626C6542794F626A656374002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000001000006020006003E002A1100000000400600000000000012000000000000000000000009000006A10100000100000000436F6E7461696E73576F72647342794F626A65637400002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000001000006020006004A002A110000000000070000000000004600000000000000000000000A000006B30100000100000000436F6E7461696E73576F726473426F756E6465645461626C6542794F626A65637400001600031144060000CC06000046000000B30100000100000022002011000000000400001100000000000000004353243C3E385F5F6C6F63616C733000020006002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000010000060200060046002A11000000007C070000000000001200000000000000000000000B000006F90100000100000000436F6E7461696E73576F726473426F756E64656442794F626A6563740000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000001000006020006003A002A1100000000EC070000000000000B00000000000000000000000C0000060B02000001000000004C69737441686F436F72617369636B000000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000010000060200060036002A110000000058080000000000001200000000000000000000000D00000616020000010000000046696C6C526F774C697374000000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000001000006020006002E002A1100000000BC080000000000003F00000000000000000000000E000006280200000100000000486173680000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000001000006020006002E002A110000000020090000000000000B0000000000000000000000100000066702000001000000002E6363746F72002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C0000000100000602000600F2000000CC0000000000000001000100EB000000000000000F000000C000000000000000130000800B0000001400008035000000150000804D00000016000080640000001800008069000000EEEFFE80A60000001B000080B20000001C000080B40000001E000080C00000001F000080C200000022000080D200000023000080D400000025000080E300000028000080EA00000029000080090034000900470009002A000900360009001600000000001100520011001700110054001100170011005900110017001100580009002D0009001300F20000003C000000EB00000001000100140000000000000003000000300000000000000030000080070000003100008013000000330000800900310009002D0009001800F200000024000000FF0000000100010013000000000000000100000018000000000000003900008009004F00F20000004800000012010000010001002300000000000000040000003C000000000000003E000080070000003F000080100000004000008022000000410000800900240009001D0009001B0005000600F20000004800000035010000010001002E00000000000000040000003C0000000000000046000080080000004700008020000000480000802C00000049000080090031000900340009001C0009001500F200000030000000630100000100010014000000000000000200000024000000000000004F00008012000000500000800900230009001500F20000003000000077010000010001000C00000000000000020000002400000000000000560000800A000000570000800900190009001500F20000003C00000083010000010001001E000000000000000300000030000000000000005E000080110000005F0000801D000000610000800900250009002D0009001800F200000024000000A10100000100010012000000000000000100000018000000000000006700008009004E00F200000054000000B3010000010001004600000000000000050000004800000000000000EEEFFE80060000006E000080170000006F00008024000000700000854500000077000080000000000900250009001C0009000C0009001800F200000024000000F90100000100010012000000000000000100000018000000000000007D00008009005500F2000000240000000B020000010001000B000000000000000100000018000000000000008400008009001D00F2000000300000001602000001000100120000000000000002000000240000000000000089000080110000008A00008009001C0005000600F20000002400000028020000010001003F000000000000000100000018000000000000008E00008009007100F20000002400000067020000010001000B000000000000000100000018000000000000009100008005006D00F4000000080000000100000000000000780000000000000020000000380000005C0000007400000090000000A8000000C0000000D8000000F80000001001000030010000480100006801000080010000AC010000C4010000E8010000000200003002000048020000740200008C020000AC020000C4020000E0020000F80200000C030000240300003C0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000032002A11000000003800000000000000070000000000000000000000150000069002000001000000006765745F547269650000000200060032002A11000000007000000000000000080000000000000000000000160000069702000001000000007365745F54726965000000020006002E002A11000000001401000000000000120000000000000000000000170000069F02000001000000002E63746F7200001600031174000000DC000000120000009F020000010000001E0024115553797374656D2E436F6C6C656374696F6E732E47656E65726963000200060032000404C93FEAC6B359D649BC250902BBABB460000000004D004400320000000401000004000000100000000300000000000100020006002E002A1100000000780100000000000013000000000000000000000018000006B102000001000000002E63746F7200002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000017000006020006002E002A1100000000DC010000000000000E000000000000000000000019000006C402000001000000002E63746F7200002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000017000006020006002E002A110000000040020000000000000E00000000000000000000001A000006D202000001000000002E63746F7200002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000017000006020006002E002A1100000000A4020000000000000F00000000000000000000001B000006E002000001000000002E63746F7200002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000017000006020006002E002A110000000008030000000000000F00000000000000000000001C000006EF02000001000000002E63746F7200002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000017000006020006002E002A11000000006C030000000000000E00000000000000000000001D000006FE0200000100000000416464000000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000017000006020006002E002A110000000024040000000000003900000000000000000000001E0000060C0300000100000000416464000000001600031170030000F0030000390000000C0300000100000016000311A0030000EC0300001400000015030000010000001A00201101000000050000110000000000000000776F72640000000002000600020006002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000170000060200060032002A110000000030050000000000008100000000000000000000001F0000064503000001000000004275696C644661696C00001600031128040000FC0400008100000045030000010000001A00201100000000060000110000000000000000776F726400000000160003115C040000C004000031000000590300000100000016002011010000000600001100000000000000006900000002000600160003115C040000F80400000F0000009D030000010000001A002011030000000600001100000000000000007375624E6F64650002000600020006002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000017000006020006002E002A1100000000AC0500000000000016000000000000000000000020000006C603000001000000005365617263680046000404C93FEAC6B359D649BC250902BBABB460000000004D004400320000000401000004040000240000003C005300650061007200630068003E0064005F005F0031003300000002000600F20000002400000090020000010001000700000000000000010000001800000000000000260000801F002300F200000024000000970200000100010008000000000000000100000018000000000000002600008024002800F20000003C0000009F0200000100010012000000000000000300000030000000000000002C000080060000002E000080110000002F00008009001D000D001F0009000A00F20000003C000000B1020000010001001300000000000000030000003000000000000000360000800600000038000080120000003900008009003D000D00270009000A00F20000003C000000C4020000010001000E000000000000000300000030000000000000004000008006000000420000800D000000430000800F0015000D00180009000A00F20000003C000000D2020000010001000E000000000000000300000030000000000000004A000080060000004C0000800D0000004D0000800F0015000D00180009000A00F20000003C000000E0020000010001000F000000000000000300000030000000000000005500008007000000570000800E000000580000800F001D000D00180009000A00F20000003C000000EF020000010001000F000000000000000300000030000000000000006000008007000000620000800E000000630000800F001D000D00180009000A00F200000030000000FE020000010001000E000000000000000200000024000000000000006C0000800D0000006D0000800D001C0009000A00F2000000840000000C0300000100010039000000000000000900000078000000000000007500008007000000EEEFFE80090000007500008010000000770000801D0000007500008027000000EEEFFE8030000000EEEFFE80310000007A000080380000007B000080220027000000000016001E00110020001F00210000000000000000000D00190009000A00F2000000C0000000450300000100010081000000000000000E000000B400000000000000830000800D00000085000080140000008600008016000000EEEFFE80180000008700008030000000860000803400000086000080450000008900008056000000EEEFFE805800000089000080600000008A000080670000008900008072000000EEEFFE80800000008B0000800D0021000D00220012001B000000000011004500430046001D00410025003500000000001600210011002400220024000000000009000A00F400000008000000700000000000000060000000540300006C030000840300009C030000B4030000C8030000E0030000F40300000C04000020040000380400004C040000640400007804000090040000A4040000BC040000D0040000E8040000FC040000140500002C050000440500005C050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000003E002A11000000007400000000000000060000000000000000000000270000066404000001000000006765745F4F7264696E616C49676E6F72654361736500002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000210000060200060036002A1100000000E000000000000000060000000000000000000000280000066A04000001000000006765745F4F7264696E616C000000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000210000060200060046002A11000000005C01000000000000060000000000000000000000290000067004000001000000006765745F496E76617269616E7443756C7475726549676E6F726543617365002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000021000006020006003E002A1100000000D0010000000000000600000000000000000000002A0000067604000001000000006765745F496E76617269616E7443756C747572650000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000021000006020006003A002A110000000040020000000000000C00000000000000000000002B0000067C04000001000000006765745F43757272656E7443756C74757265002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000210000060200060046002A1100000000BC020000000000000C00000000000000000000002C0000068804000001000000006765745F43757272656E7443756C7475726549676E6F7265436173650000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000021000006020006002E002A110000000020030000000000000800000000000000000000002D000006940400000100000000437265617465002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000021000006020006002E002A110000000084030000000000003700000000000000000000002F0000069C04000001000000002E6363746F72002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C0000002100000602000600F200000024000000640400000100010006000000000000000100000018000000000000005B00008011002B00F2000000240000006A0400000100010006000000000000000100000018000000000000006B00008011002100F200000024000000700400000100010006000000000000000100000018000000000000007B00008011003400F200000024000000760400000100010006000000000000000100000018000000000000008B00008011002A00F2000000240000007C040000010001000C000000000000000100000018000000000000009900008011005F00F20000002400000088040000010001000C00000000000000010000001800000000000000A700008011005E00F20000002400000094040000010001000800000000000000010000001800000000000000B30000800D004500F2000000480000009C040000010001003700000000000000040000003C000000000000004F0000800B0000005F000080160000006F000080260000007F00008009006D00090064000900940009008B00F400000008000000D600000000000000400000007405000098050000B0050000CC050000E4050000140600002C06000050060000680600008C060000A4060000D0060000E8060000000700001807000030070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000032002A11000000005C01000000000000660100000000000000000000460000069106000001000000004D6F76654E6578740000001600031104000000F80000006601000091060000010000001E0024115553797374656D2E436F6C6C656374696F6E732E47656E65726963001600031138000000F4000000F9000000D40600000100000016002011020000000B0000110000000000000000630000001600031170000000F00000004E0000005F070000010000001A002011030000000B0000110000000000000000776F7264000000001A002011040000000B00001100000000000000006F666673657400000200060002000600020006005E000404C93FEAC6B359D649BC250902BBABB460000000004D004400320000000402000004000000100000000300000000000100040300002C00000004000000000000000000000021000000650100003700000063010000B30000003B01000002000600F200000050010000910600000100010066010000000000001A0000004401000000000000EEEFFE80210000009400008029000000940000802B0000009600008037000000980000803E000000EEEFFE80430000009A00008055000000EEEFFE80570000009D000080680000009C000080830000009F0000808B0000009F00008097000000A1000080B3000000A3000080BF000000EEEFFE80C1000000A7000080CE000000A9000080DA000000AA000080EB000000AB00008015010000EEEFFE801C010000AE0000802D010000A500008035010000B00000803C010000980000804E0100009800008064010000B2000080000000000D001E001F002B000D00200012001B0000000000110021000000000015002C0011004800110025002600350011003E001500280000000000190029001D0032001D003E001D0058000000000019002A0015002900110012002E0031001D002C0009000A00F40000000800000070000000000000000800000048070000600700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000042002A1100000000D4010000000000000C0000000000000000000000400000060106000001000000003C4275696C6441686F436F72617369636B3E625F5F305F300000001600031104000000A00100000C00000001060000010000000A0024115553797374656D00120024115553797374656D2E44617461000000001A0024115553797374656D2E446174612E53716C436C69656E7400001A0024115553797374656D2E446174612E53716C54797065730000001E002411554D6963726F736F66742E53716C5365727665722E53657276657200160024115553797374656D2E586D6C2E4C696E7100000000120024115553797374656D2E4C696E71000000000E0024115547616E73732E5465787400160024115553797374656D2E436F6C6C656374696F6E73001E0024115553797374656D2E436F6C6C656374696F6E732E47656E6572696300220024115553797374656D2E53656375726974792E43727970746F677261706879000000120024115553797374656D2E54657874000000001A0024115553797374656D2E476C6F62616C697A6174696F6E000000020006002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040000000C00000001000D000200060036002A110000000040020000000000000D0000000000000000000000410000060D06000001000000003C486173683E625F5F31335F3000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C0000004000000602000600F20000002400000001060000010001000C00000000000000010000001800000000000000140000802F004500F2000000240000000D060000010001000D000000000000000100000018000000000000008E0000805E006E00F40000000800000001000000000000001000000078070000A0070000B8070000D407000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000052002A1100000000BC00000000000000770000000000000000000000430000061A06000001000000003C436F6E7461696E73576F726473426F756E6465645461626C6542794F626A6563743E625F5F3000000000160003110400000088000000770000001A0600000100000016002011000000000A0000110000000000000000656E6400020006002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C0000004000000602000600F20000003C0000001A06000001000100770000000000000003000000300000000000000072000080280000007300008074000000740000800D004F000D0072000D002100F400000008000000010000000000000008000000EC070000240800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000002E002A1100000000F4000000000000000E000000000000000000000021000006DC03000001000000002E63746F7200001600031104000000BC0000000E000000DC030000010000000A0024115553797374656D001E0024115553797374656D2E436F6C6C656374696F6E732E47656E65726963001A0024115553797374656D2E476C6F62616C697A6174696F6E000000120024115553797374656D2E4C696E7100000000120024115553797374656D2E54657874000000000200060032000404C93FEAC6B359D649BC250902BBABB460000000004D004400320000000401000004000000100000000300000000000500020006002E002A1100000000580100000000000028000000000000000000000022000006EA0300000100000000457175616C73002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000210000060200060036002A1100000000C4010000000000001100000000000000000000002300000612040000010000000047657448617368436F6465000000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C0000002100000602000600F20000003C000000DC030000010001000E000000000000000300000030000000000000000D000080060000000F0000800D0000001000008009003C000D00260009000A00F200000024000000EA030000010001002800000000000000010000001800000000000000140000810D002D00F200000024000000120400000100010011000000000000000100000018000000000000001A0000800D004D00F400000008000000D600000000000000180000003C08000050080000680800008008000098080000B408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000032002A11000000003800000000000000070000000000000000000000110000067202000001000000006765745F496E64657800000200060032002A11000000007000000000000000080000000000000000000000120000067902000001000000007365745F496E64657800000200060032002A1100000000A800000000000000070000000000000000000000130000068102000001000000006765745F576F72640000000200060032002A1100000000E000000000000000080000000000000000000000140000068802000001000000007365745F576F726400000002000600F20000002400000072020000010001000700000000000000010000001800000000000000100000801C002000F200000024000000790200000100010008000000000000000100000018000000000000001000008021002500F20000002400000081020000010001000700000000000000010000001800000000000000180000801E002200F200000024000000880200000100010008000000000000000100000018000000000000001800008023002700F400000008000000700000000000000020000000CC080000E4080000FC080000140900002C090000440900005C0900007409000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000032002A1100000000380000000000000007000000000000000000000030000006D304000001000000006765745F4E6578740000000200060032002A1100000000700000000000000008000000000000000000000031000006DA04000001000000007365745F4E6578740000000200060032002A1100000000A80000000000000007000000000000000000000032000006E204000001000000006765745F4973576F7264000200060032002A1100000000E00000000000000008000000000000000000000033000006E904000001000000007365745F4973576F7264000200060032002A1100000000180100000000000007000000000000000000000034000006F104000001000000006765745F4661696C0000000200060032002A1100000000500100000000000008000000000000000000000035000006F804000001000000007365745F4661696C0000000200060032002A11000000008801000000000000070000000000000000000000360000060005000001000000006765745F506172656E74000200060032002A1100000000C001000000000000080000000000000000000000370000060705000001000000007365745F506172656E74000200060032002A1100000000F801000000000000070000000000000000000000380000060F05000001000000006765745F576F72640000000200060032002A11000000003002000000000000080000000000000000000000390000061605000001000000007365745F576F7264000000020006002E002A1100000000D4020000000000001D00000000000000000000003A0000061E05000001000000002E63746F72000016000311340200009C0200001D0000001E050000010000001E0024115553797374656D2E436F6C6C656374696F6E732E47656E65726963000200060032000404C93FEAC6B359D649BC250902BBABB460000000004D004400320000000401000004000000100000000300000000000100020006002E002A110000000038030000000000001E00000000000000000000003B0000063B05000001000000002E63746F7200002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C0000003A000006020006002E002A1100000000EC030000000000007500000000000000000000003C00000659050000010000000041646400000000160003113C030000B80300007500000059050000010000001600201100000000080000110000000000000000630000001A002011010000000800001100000000000000006E6F646500000000020006002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C0000003A000006020006003A002A1100000000C8040000000000003300000000000000000000003D000006CE05000001000000004578706C6F72654661696C4C696E6B0000000016000311F00300009404000033000000CE050000010000001A002011000000000900001100000000000000006E6F646500000000160003112C040000900400001C000000D60500000100000016002011030000000900001100000000000000006300000002000600020006002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C0000003A00000602000600F200000024000000D3040000010001000700000000000000010000001800000000000000100000802E003200F200000024000000DA0400000100010008000000000000000100000018000000000000001000008033003700F200000024000000E2040000010001000700000000000000010000001800000000000000180000801E002200F200000024000000E90400000100010008000000000000000100000018000000000000001800008023002700F200000024000000F1040000010001000700000000000000010000001800000000000000200000801C002000F200000024000000F80400000100010008000000000000000100000018000000000000002000008021002500F20000002400000000050000010001000700000000000000010000001800000000000000280000801E002200F200000024000000070500000100010008000000000000000100000018000000000000002800008023002700F2000000240000000F050000010001000700000000000000010000001800000000000000300000801E002200F200000024000000160500000100010008000000000000000100000018000000000000003000008023002F00F2000000480000001E050000010001001D00000000000000040000003C0000000000000035000080060000003700008011000000380000801C00000039000080090016000D0017000D00310009000A00F2000000480000003B050000010001001E00000000000000040000003C000000000000003F000080060000004100008011000000420000801D00000043000080090036000D0017000D00390009000A00F20000006C000000590500000100010075000000000000000700000060000000000000004C000080080000004E000080180000004F00008055000000510000805E000000520000806C0000005400008073000000560000800D001D000D00350011005D000D00210011003400110024000D001900F200000090000000CE0500000100010033000000000000000A000000840000000000000060000080020000006200008006000000EEEFFE80080000006200008010000000640000801F00000065000080220000006500008024000000EEEFFE80280000006200008031000000680000800D001D001F0023000000000016001B00110034001100220023002F00000000001C001E000D001900F4000000080000003E01000000000000700000008C090000A4090000BC090000D4090000EC090000080A0000200A00003C0A0000540A00006C0A0000840A00009C0A0000B40A0000D00A0000E80A0000040B00001C0B0000340B00004C0B0000640B00007C0B0000900B0000A80B0000BC0B0000D40B0000E80B0000000C0000200C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000002E002A11000000006400000000000000140000000000000000000000240000062304000001000000002E63746F7200002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C00000021000006020006002E002A1100000000C8000000000000001A000000000000000000000025000006370400000100000000457175616C73002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C000000210000060200060036002A110000000034010000000000001300000000000000000000002600000651040000010000000047657448617368436F6465000000002E000404C93FEAC6B359D649BC250902BBABB460000000004D0044003200000004010000040100000C0000002100000602000600F20000003C000000230400000100010014000000000000000300000030000000000000002300008006000000250000801300000026000080090055000D004E0009000A00F20000002400000037040000010001001A000000000000000100000018000000000000002A0000800D004700F200000024000000510400000100010013000000000000000100000018000000000000002F0000800D004000F400000008000000D60000000000000018000000380C00004C0C0000640C00007C0C0000940C0000B00C0000FFFFFFFF1A092FF1F0030000B80300005D000000010000007502000001000000D50B000001000000E904000001000000BD040000010000001509000001000000790400000100000081080000010000008D06000001000000090A000001000000BD0B0000010000000102000001000000850A000001000000550A0000010000009100000001000000AD020000010000004509000001000000A504000001000000B508000001000000D1060000010000003D0A000001000000E90B00000100000025080000010000002D06000001000000B9070000010000003D030000010000005D05000001000000A509000001000000C502000001000000A107000001000000390C000001000000A90B0000010000007D0B0000010000003D080000010000009104000001000000650400000100000039040000010000000D04000001000000E103000001000000B503000001000000790700000100000021000000010000003102000001000000E5080000010000004D04000001000000150500000100000051080000010000005106000001000000ED07000001000000D509000001000000910B0000010000004505000001000000D507000001000000C501000001000000310100000100000075000000010000009D030000010000002D050000010000008101000001000000010C000001000000B10C0000010000003107000001000000D10A00000100000061070000010000006901000001000000C9030000010000009905000001000000050B0000010000004D0B0000010000005D090000010000001D0B0000010000002D09000001000000C100000001000000E102000001000000B1050000010000007509000001000000210A000001000000D104000001000000ED090000010000004D0C00000100000001070000010000006D0A000001000000210C000001000000F9000000010000000D030000010000006D03000001000000FD040000010000007D0C000001000000CD08000001000000FD080000010000009D0A000001000000F902000001000000A90000000100000069060000010000004901000001000000A506000001000000110100000100000019070000010000002503000001000000E5050000010000004902000001000000AD01000001000000F503000001000000CD05000001000000350B00000100000055030000010000008503000001000000E906000001000000E901000001000000D900000001000000750500000100000021040000010000001506000001000000650B0000010000008D020000010000000100000001000000650C0000010000006908000001000000E90A0000010000008D09000001000000BD09000001000000B50A000001000000950C000001000000990800000100000049070000010000003900000001000000012400000208000004010000080200000008000000040040000000000000000001040000020800000401000008020000100000020000000000000000000000000002000002000000040000000800000110020000002000000000000000000000010400000208000005010800080200041000008000000000000000000000000001002000020880020401000008000000100000000000000000000000000000000100000002000000040000000800000000000000000000000100100000000000010404000A08800004010000080200000000000000000000000000000000000001040000020800001400010008000004400000000000000000000000000000000000000000000000000000000000000000020010000000002000000000000000000000000000008000000000000420000000400000000000000000000000000002000000010000000800000004000000000000000080000800000000000000010200080001000000080000000400000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000014004108000000000040000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000C000000180000003C0000004800000054000000600000006C0000007800000084000000900000009C000000A8000000B4000000C0000000CC000000D8000000E4000000F0000000FC0000000801000014010000200100002C0100003801000044010000500100005C01000068010000E0010000EC010000F801000004020000100200001C0200002802000034020000400200004C0200005802000064020000700200007C0200008802000094020000A0020000AC020000B8020000C4020000D0020000DC020000E8020000F4020000000300000C03000018030000240300003003000048030000600300006C0300007803000084030000900300009C030000A8030000B4030000C0030000CC030000D8030000E4030000F0030000FC0300000804000014040000200400002C0400003804000044040000500400005C0400006804000074040000800400008C040000A4040000B0040000BC040000C8040000D4040000E0040000EC040000F804000004050000100500001C05000034050000400500004C0500005805000064050000700500008805000094050000A0050000AC050000B8050000D0050000DC0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E002511000000000400000001004275696C6441686F436F72617369636B000016002911000000000400000001003036303030303031000022002511000000003C0200000100436F6E7461696E73576F7264735461626C650000000016002911000000003C0200000100303630303030303200001A00251100000000AC0200000100436F6E7461696E73576F726473001600291100000000AC020000010030363030303030330000160025110000000018030000010046696C6C526F770000001600291100000000180300000100303630303030303400001E00251100000000B8030000010043726561746541686F436F72617369636B001600291100000000B80300000100303630303030303500001E0025110000000078040000010044656C65746541686F436F72617369636B001600291100000000780400000100303630303030303600001E00251100000000E80400000100436C65617241686F436F72617369636B00001600291100000000E80400000100303630303030303700002A00251100000000580500000100436F6E7461696E73576F7264735461626C6542794F626A656374000000001600291100000000580500000100303630303030303800002200251100000000D00500000100436F6E7461696E73576F72647342794F626A656374001600291100000000D005000001003036303030303039000010000000000000000000000000000000000000000000000000000000FFFFFFFF1A092FF100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E00251100000000440600000100436F6E7461696E73576F726473426F756E6465645461626C6542794F626A656374001600291100000000440600000100303630303030306100002A00251100000000040700000100436F6E7461696E73576F726473426F756E64656442794F626A65637400001600291100000000040700000100303630303030306200001E002511000000008007000001004C69737441686F436F72617369636B0000001600291100000000800700000100303630303030306300001A00251100000000F0070000010046696C6C526F774C6973740000001600291100000000F007000001003036303030303064000012002511000000005C080000010048617368000016002911000000005C0800000100303630303030306500001600251100000000C008000001002E6363746F72000000001600291100000000C008000001003036303030303130000016002511000000000400000003006765745F54726965000016002911000000000400000003003036303030303135000016002511000000003C00000003007365745F54726965000016002911000000003C00000003003036303030303136000012002511000000007400000003002E63746F720016002911000000007400000003003036303030303137000012002511000000001801000003002E63746F720016002911000000001801000003003036303030303138000012002511000000007C01000003002E63746F720016002911000000007C0100000300303630303030313900001200251100000000E001000003002E63746F72001600291100000000E001000003003036303030303161000012002511000000004402000003002E63746F72001600291100000000440200000300303630303030316200001200251100000000A802000003002E63746F72001600291100000000A802000003003036303030303163000012002511000000000C030000030041646400000016002911000000000C030000030030363030303031640000120025110000000070030000030041646400000016002911000000007003000003003036303030303165000016002511000000002804000003004275696C644661696C0016002911000000002804000003003036303030303166000016002511000000003405000003005365617263680000000016002911000000003405000003003036303030303230000022002511000000000400000006006765745F4F7264696E616C49676E6F726543617365001600291100000000040000000600303630303030323700001A002511000000007800000006006765745F4F7264696E616C0000001600291100000000780000000600303630303030323800002E00251100000000E400000006006765745F496E76617269616E7443756C7475726549676E6F726543617365000000001600291100000000E400000006003036303030303239000022002511000000006001000006006765745F496E76617269616E7443756C7475726500001600291100000000600100000600303630303030326100002200251100000000D401000006006765745F43757272656E7443756C74757265000000001600291100000000D40100000600303630303030326200002A002511000000004402000006006765745F43757272656E7443756C7475726549676E6F72654361736500001600291100000000440200000600303630303030326300001600251100000000C00200000600437265617465000000001600291100000000C002000006003036303030303264000016002511000000002403000006002E6363746F72000000001600291100000000240300000600303630303030326600001600251100000000040000000A004D6F76654E65787400001600291100000000040000000A003036303030303436000026002511000000000400000008003C4275696C6441686F436F72617369636B3E625F5F305F3000001600291100000000040000000800303630303030343000001A00251100000000D801000008003C486173683E625F5F31335F30001600291100000000D801000008003036303030303431000036002511000000000400000009003C436F6E7461696E73576F726473426F756E6465645461626C6542794F626A6563743E625F5F3000000016002911000000000400000009003036303030303433000012002511000000000400000004002E63746F72001600291100000000040000000400303630303030323100001600251100000000F80000000400457175616C73000000001600291100000000F80000000400303630303030323200001A002511000000005C010000040047657448617368436F646500000016002911000000005C01000004003036303030303233000016002511000000000400000002006765745F496E6465780016002911000000000400000002003036303030303131000016002511000000003C00000002007365745F496E6465780016002911000000003C00000002003036303030303132000016002511000000007400000002006765745F576F726400001600291100000000740000000200303630303030313300001600251100000000AC00000002007365745F576F726400001600291100000000AC00000002003036303030303134000016002511000000000400000007006765745F4E657874000016002911000000000400000007003036303030303330000016002511000000003C00000007007365745F4E657874000016002911000000003C0000000700303630303030333100001A002511000000007400000007006765745F4973576F7264000000001600291100000000740000000700303630303030333200001A00251100000000AC00000007007365745F4973576F7264000000001600291100000000AC0000000700303630303030333300001600251100000000E400000007006765745F4661696C00001600291100000000E400000007003036303030303334000016002511000000001C01000007007365745F4661696C000016002911000000001C0100000700303630303030333500001A002511000000005401000007006765745F506172656E74000000001600291100000000540100000700303630303030333600001A002511000000008C01000007007365745F506172656E740000000016002911000000008C0100000700303630303030333700001600251100000000C401000007006765745F576F726400001600291100000000C40100000700303630303030333800001600251100000000FC01000007007365745F576F726400001600291100000000FC01000007003036303030303339000012002511000000003402000007002E63746F72001600291100000000340200000700303630303030336100001200251100000000D802000007002E63746F72001600291100000000D802000007003036303030303362000012002511000000003C030000070041646400000016002911000000003C0300000700303630303030336300001E00251100000000F003000007004578706C6F72654661696C4C696E6B0000001600291100000000F003000007003036303030303364000012002511000000000400000005002E63746F72001600291100000000040000000500303630303030323400001600251100000000680000000500457175616C73000000001600291100000000680000000500303630303030323500001A00251100000000CC000000050047657448617368436F64650000001600291100000000CC000000050030363030303032360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF770931010100000017000C8E1800E66419000200F8030000E80600002C00000020010000000000000000000016000000190000000000EEC00000000000000000FFFF000000000000FFFFFFFF00000000FFFF0000000000000000000000000D002409000000000000180400000100000000000000000000000000000055736572446566696E656446756E6374696F6E7300373141414145453800000000000000FFFF000000000000FFFFFFFF00000000FFFF0000000000000000000000001400E400000000000000C00000000100000000000000000000000000000047616E73732E546578742E576F72644D6174636800363236423346313800000000000000FFFF000000000000FFFFFFFF00000000FFFF0000000000000000000000000E00B0050000000000008C0300000100000000000000000000000000000047616E73732E546578742E41686F436F72617369636B0031434435303842360000000000FFFF000000000000FFFFFFFF00000000FFFF0000000000000000000000001300C801000000000000AC0000000100000000000000000000000000000047616E73732E546578742E4F7264696E616C43686172436F6D70617265720045313736333843390000000000FFFF000000000000FFFFFFFF00000000FFFF00000000000000000000000016003801000000000000AC0000000100000000000000000000000000000047616E73732E546578742E43756C7475726543686172436F6D70617265720037374537384337360000000000FFFF000000000000FFFFFFFF00000000FFFF0000000000000000000000000F008803000000000000940100000100000000000000000000000000000047616E73732E546578742E43686172436F6D70617265720038394531464342340000000000000000FFFF000000000000FFFFFFFF00000000FFFF0000000000000000000000001500CC04000000000000740300000100000000000000000000000000000047616E73732E546578742E547269650034323139303734390000000000000000FFFF000000000000FFFFFFFF00000000FFFF00000000000000000000000011004402000000000000680000000100000000000000000000000000000055736572446566696E656446756E6374696F6E732E3C3E6300464146343644353400000000000000FFFF000000000000FFFFFFFF00000000FFFF0000000000000000000000001200C000000000000000540000000100000000000000000000000000000055736572446566696E656446756E6374696F6E732E3C3E635F5F446973706C6179436C617373395F30003536313438444339000000000000FFFF000000000000FFFFFFFF00000000FFFF00000000000000000000000010006001000000000000680100000100000000000000000000000000000047616E73732E546578742E41686F436F72617369636B2E3C5365617263683E645F5F31330045334336314439430000002DBA2EF10100000000000000EB0000000000000000000000000000000000000001000000EB000000140000000000000000000000000000000000000001000000FF00000013000000000000000000000000000000000000000100000012010000230000000000000000000000000000000000000001000000350100002E000000000000000000000000000000000000000100000063010000140000000000000000000000000000000000000001000000770100000C0000000000000000000000000000000000000001000000830100001E0000000000000000000000000000000000000001000000A1010000120000000000000000000000000000000000000001000000B3010000460000000000000000000000000000000000000001000000F90100001200000000000000000000000000000000000000010000000B0200000B000000000000000000000000000000000000000100000016020000120000000000000000000000000000000000000001000000280200003F0000000000000000000000000000000000000001000000670200000B00000000000000000000000000000000000000010000007202000007000000000000000100000000000000000000000100000079020000080000000000000001000000000000000000000001000000810200000700000000000000010000000000000000000000010000008802000008000000000000000100000000000000000000000100000090020000070000000000000002000000000000000000000001000000970200000800000000000000020000000000000000000000010000009F020000120000000000000002000000000000000000000001000000B1020000130000000000000002000000000000000000000001000000C40200000E0000000000000002000000000000000000000001000000D20200000E0000000000000002000000000000000000000001000000E00200000F0000000000000002000000000000000000000001000000EF0200000F0000000000000002000000000000000000000001000000FE0200000E00000000000000020000000000000000000000010000000C03000039000000000000000200000000000000000000000100000045030000810000000000000002000000000000000000000001000000C6030000160000000000000002000000000000000000000001000000DC0300000E0000000000000003000000000000000000000001000000EA0300002800000000000000030000000000000000000000010000001204000011000000000000000300000000000000000000000100000023040000140000000000000004000000000000000000000001000000370400001A000000000000000400000000000000000000000100000051040000130000000000000004000000000000000000000001000000640400000600000000000000050000000000000000000000010000006A04000006000000000000000500000000000000000000000100000070040000060000000000000005000000000000000000000001000000760400000600000000000000050000000000000000000000010000007C0400000C0000000000000005000000000000000000000001000000880400000C0000000000000005000000000000000000000001000000940400000800000000000000050000000000000000000000010000009C040000370000000000000005000000000000000000000001000000D3040000070000000000000006000000000000000000000001000000DA040000080000000000000006000000000000000000000001000000E2040000070000000000000006000000000000000000000001000000E9040000080000000000000006000000000000000000000001000000F1040000070000000000000006000000000000000000000001000000F804000008000000000000000600000000000000000000000100000000050000070000000000000006000000000000000000000001000000070500000800000000000000060000000000000000000000010000000F050000070000000000000006000000000000000000000001000000160500000800000000000000060000000000000000000000010000001E0500001D00000000000000060000000000000000000000010000003B0500001E000000000000000600000000000000000000000100000059050000750000000000000006000000000000000000000001000000CE050000330000000000000006000000000000000000000001000000010600000C00000000000000070000000000000000000000010000000D0600000D00000000000000070000000000000000000000010000001A060000770000000000000008000000000000000000000001000000910600006601000000000000090000000000000000000000020002000D01000000000100FFFFFFFF00000000F70700000802000000000000FFFFFFFF00000000FFFFFFFF0A000A00000001000200030004000500060007000800090001000100010001000100010001000100010001000000000037000000370000006A0000006A0000006A0000009E000000000000000000000037000000463A5C50726F6A656374735C41686F436F72617369636B5C41686F436F72617369636B2E53716C436C725C436F6E7461696E732E637300463A5C50726F6A656374735C41686F436F72617369636B5C41686F436F72617369636B5C41686F436F72617369636B2E637300463A5C50726F6A656374735C41686F436F72617369636B5C41686F436F72617369636B5C43686172436F6D70617265722E637300463A5C50726F6A656374735C41686F436F72617369636B5C41686F436F72617369636B5C547269652E6373000000FEEFFEEF010000000100000000010000000000000000000000FFFFFFFFFFFFFFFFFFFF0C00FFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000942E3101F0CEA95D01000000F008FDC110632F41A346158C5BAC73A9180100002F4C696E6B496E666F002F6E616D6573002F7372632F686561646572626C6F636B002F7372632F66696C65732F663A5C70726F6A656374735C61686F636F72617369636B5C61686F636F72617369636B2E73716C636C725C636F6E7461696E732E6373002F7372632F66696C65732F663A5C70726F6A656374735C61686F636F72617369636B5C61686F636F72617369636B5C61686F636F72617369636B2E6373002F7372632F66696C65732F663A5C70726F6A656374735C61686F636F72617369636B5C61686F636F72617369636B5C63686172636F6D70617265722E6373002F7372632F66696C65732F663A5C70726F6A656374735C61686F636F72617369636B5C61686F636F72617369636B5C747269652E637300070000000E00000001000000B036000000000000A20000000A0000000A00000006000000000000000500000011000000070000006400000009000000E10000000B000000220000000800000000000000DC51330100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001A000000200000008C010000380000009B0C00003800000000000000EE010000040100006800000068000000680000006800000028000000B80D0000A009000060050000D4020000C00200002001000090020000C8010000B408000000020000B80700002C000000C80C0000030000003F0000000600000038000000390000003A0000003B0000003C0000003D0000003E000000070000000D0000000E00000008000000090000000A0000000B0000000C0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000310000003000000032000000330000003400000035000000360000003700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 AS N'AhoCorasick.SqlClr.pdb';
14 |
15 |
16 | GO
17 | PRINT N'Creating [dbo].[ContainsWords]...';
18 |
19 |
20 | GO
21 | CREATE FUNCTION [dbo].[ContainsWords]
22 | (@xml XML, @text NVARCHAR (MAX), @culture NVARCHAR (MAX))
23 | RETURNS BIT
24 | AS
25 | EXTERNAL NAME [AhoCorasick.SqlClr].[UserDefinedFunctions].[ContainsWords]
26 |
27 |
28 | GO
29 | PRINT N'Creating [dbo].[CreateAhoCorasick]...';
30 |
31 |
32 | GO
33 | CREATE FUNCTION [dbo].[CreateAhoCorasick]
34 | (@xml XML, @culture NVARCHAR (MAX))
35 | RETURNS NVARCHAR (MAX)
36 | AS
37 | EXTERNAL NAME [AhoCorasick.SqlClr].[UserDefinedFunctions].[CreateAhoCorasick]
38 |
39 |
40 | GO
41 | PRINT N'Creating [dbo].[DeleteAhoCorasick]...';
42 |
43 |
44 | GO
45 | CREATE FUNCTION [dbo].[DeleteAhoCorasick]
46 | (@obj NVARCHAR (MAX))
47 | RETURNS BIT
48 | AS
49 | EXTERNAL NAME [AhoCorasick.SqlClr].[UserDefinedFunctions].[DeleteAhoCorasick]
50 |
51 |
52 | GO
53 | PRINT N'Creating [dbo].[ClearAhoCorasick]...';
54 |
55 |
56 | GO
57 | CREATE FUNCTION [dbo].[ClearAhoCorasick]
58 | ( )
59 | RETURNS BIT
60 | AS
61 | EXTERNAL NAME [AhoCorasick.SqlClr].[UserDefinedFunctions].[ClearAhoCorasick]
62 |
63 |
64 | GO
65 | PRINT N'Creating [dbo].[ContainsWordsByObject]...';
66 |
67 |
68 | GO
69 | CREATE FUNCTION [dbo].[ContainsWordsByObject]
70 | (@text NVARCHAR (MAX), @obj NVARCHAR (MAX))
71 | RETURNS BIT
72 | AS
73 | EXTERNAL NAME [AhoCorasick.SqlClr].[UserDefinedFunctions].[ContainsWordsByObject]
74 |
75 |
76 | GO
77 | PRINT N'Creating [dbo].[ContainsWordsBoundedByObject]...';
78 |
79 |
80 | GO
81 | CREATE FUNCTION [dbo].[ContainsWordsBoundedByObject]
82 | (@text NVARCHAR (MAX), @obj NVARCHAR (MAX))
83 | RETURNS BIT
84 | AS
85 | EXTERNAL NAME [AhoCorasick.SqlClr].[UserDefinedFunctions].[ContainsWordsBoundedByObject]
86 |
87 |
88 | GO
89 | PRINT N'Creating [dbo].[ContainsWordsTable]...';
90 |
91 |
92 | GO
93 | CREATE FUNCTION [dbo].[ContainsWordsTable]
94 | (@xml XML, @text NVARCHAR (MAX), @culture NVARCHAR (MAX))
95 | RETURNS
96 | TABLE (
97 | [Index] INT NULL,
98 | [Word] NVARCHAR (MAX) NULL)
99 | AS
100 | EXTERNAL NAME [AhoCorasick.SqlClr].[UserDefinedFunctions].[ContainsWordsTable]
101 |
102 |
103 | GO
104 | PRINT N'Creating [dbo].[ContainsWordsTableByObject]...';
105 |
106 |
107 | GO
108 | CREATE FUNCTION [dbo].[ContainsWordsTableByObject]
109 | (@text NVARCHAR (MAX), @obj NVARCHAR (MAX))
110 | RETURNS
111 | TABLE (
112 | [Index] INT NULL,
113 | [Word] NVARCHAR (MAX) NULL)
114 | AS
115 | EXTERNAL NAME [AhoCorasick.SqlClr].[UserDefinedFunctions].[ContainsWordsTableByObject]
116 |
117 |
118 | GO
119 | PRINT N'Creating [dbo].[ContainsWordsBoundedTableByObject]...';
120 |
121 |
122 | GO
123 | CREATE FUNCTION [dbo].[ContainsWordsBoundedTableByObject]
124 | (@text NVARCHAR (MAX), @obj NVARCHAR (MAX))
125 | RETURNS
126 | TABLE (
127 | [Index] INT NULL,
128 | [Word] NVARCHAR (MAX) NULL)
129 | AS
130 | EXTERNAL NAME [AhoCorasick.SqlClr].[UserDefinedFunctions].[ContainsWordsBoundedTableByObject]
131 |
132 |
133 | GO
134 | PRINT N'Creating [dbo].[ListAhoCorasick]...';
135 |
136 |
137 | GO
138 | CREATE FUNCTION [dbo].[ListAhoCorasick]
139 | ( )
140 | RETURNS
141 | TABLE (
142 | [Hash] NVARCHAR (MAX) NULL)
143 | AS
144 | EXTERNAL NAME [AhoCorasick.SqlClr].[UserDefinedFunctions].[ListAhoCorasick]
145 |
146 |
147 | GO
148 | PRINT N'Update complete.';
149 |
150 |
151 | GO
152 |
--------------------------------------------------------------------------------