Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
HarmonizedTextMap.cs
2using System.Text.RegularExpressions;
4
5namespace Waher.Runtime.Text
6{
11 public class HarmonizedTextMap
12 {
13 private readonly Dictionary<string, MappingExpression> mappings = new Dictionary<string, MappingExpression>();
14 private MappingStep mappingsStep0 = null;
15 private bool hasMaps = false;
16
22 {
23 }
24
31 public void RegisterMapping(string RegexPattern, string MapTo)
32 {
33 this.RegisterMapping(RegexPattern, MapTo, null);
34 }
35
44 public void RegisterMapping(string RegexPattern, string MapTo, object Tag)
45 {
46 lock (this.mappings)
47 {
48 if (!this.mappings.TryGetValue(RegexPattern, out MappingExpression Exp))
49 {
50 Exp = new MappingExpression()
51 {
52 Pattern = RegexPattern,
53 Expression = new Regex(RegexPattern, RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant),
54 Tag = Tag
55 };
56 this.mappings[RegexPattern] = Exp;
57 }
58
59 Dictionary<string, bool> Names = new Dictionary<string, bool>();
60
61 foreach (string Name in Exp.Expression.GetGroupNames())
62 Names[Name] = true;
63
65 int i = MapTo.IndexOf('{');
66 int j;
67
68 while (i >= 0)
69 {
70 j = MapTo.IndexOf('}', i + 1);
71 if (j < 0)
72 break;
73
74 string Name = MapTo.Substring(i + 1, j - i - 1);
75
76 if (Names.ContainsKey(Name))
77 {
78 Parameters.Add(new KeyValuePair<int, string>(i, Name));
79 MapTo = MapTo.Remove(i, j - i + 1);
80 i = MapTo.IndexOf('{', i);
81 }
82 else
83 i = MapTo.IndexOf('{', i + 1);
84 }
85
86 Parameters.Reverse();
87
88 Exp.MapSeed = MapTo;
89 Exp.Parameters = Parameters.ToArray();
90
91 this.hasMaps = true;
92 this.mappingsStep0 = null;
93 }
94 }
95
101 public bool UnregisterMapping(string RegexPattern)
102 {
103 lock (this.mappings)
104 {
105 if (this.mappings.Remove(RegexPattern))
106 {
107 this.hasMaps = this.mappings.Count > 0;
108 this.mappingsStep0 = null;
109 return true;
110 }
111 else
112 return false;
113 }
114 }
115
121 public int UnregisterMappings(object Tag)
122 {
123 if (Tag is null)
124 return 0;
125
126 ChunkedList<string> ToRemove = null;
127 int NrRemoved = 0;
128
129 lock (this.mappings)
130 {
131 foreach (KeyValuePair<string, MappingExpression> P in this.mappings)
132 {
133 if (!(P.Value.Tag is null) && P.Value.Tag.Equals(Tag))
134 {
135 if (ToRemove is null)
136 ToRemove = new ChunkedList<string>();
137
138 ToRemove.Add(P.Key);
139 }
140 }
141
142 if (!(ToRemove is null))
143 {
144 ChunkNode<string> Loop = ToRemove.FirstChunk;
145
146 while (!(Loop is null))
147 {
148 for (int i = Loop.Start, c = Loop.Pos; i < c; i++)
149 {
150 if (this.mappings.Remove(Loop[i]))
151 NrRemoved++;
152 }
153 Loop = Loop.Next;
154 }
155 }
156 }
157
158 return NrRemoved;
159 }
160
167 public bool TryMap(string InputString, out string Harmonized)
168 {
169 Harmonized = null;
170
171 if (this.hasMaps)
172 {
173 MappingStep Step = this.mappingsStep0;
174 MappingStep Next;
175 char ch2;
176
177 if (Step is null)
178 {
179 MappingExpression[] Expressions;
180
181 lock (this.mappings)
182 {
183 Expressions = new MappingExpression[this.mappings.Count];
184 this.mappings.Values.CopyTo(Expressions, 0);
185 }
186
187 Step = this.mappingsStep0 = MappingStep.CalcStep((char)0, Expressions);
188 }
189
190 foreach (char ch in InputString)
191 {
192 if (!(Step.Expressions is null))
193 {
194 foreach (Mapping Map in Step.Expressions)
195 {
196 Match M = Map.Expression.Match(InputString);
197 if (M.Success && M.Index == 0 && M.Length == InputString.Length)
198 {
199 Harmonized = Map.MapSeed;
200 foreach (KeyValuePair<int, string> P in Map.Parameters)
201 Harmonized = Harmonized.Insert(P.Key, M.Groups[P.Value]?.Value ?? string.Empty);
202
203 return true;
204 }
205 }
206 }
207
208 if (Step.Next is null)
209 return false;
210
211 Next = null;
212
213 foreach (MappingStep Step2 in Step.Next)
214 {
215 ch2 = Step2.Character;
216 if (ch2 == ch)
217 {
218 Next = Step2;
219 break;
220 }
221 else if (ch2 > ch)
222 return false;
223 }
224
225 if (Next is null)
226 return false;
227
228 Step = Next;
229 }
230
231 if (!(Step.Next is null))
232 return false;
233
234 if (!(Step.Expressions is null))
235 {
236 foreach (Mapping Map in Step.Expressions)
237 {
238 Match M = Map.Expression.Match(InputString);
239 if (M.Success && M.Index == 0 && M.Length == InputString.Length)
240 {
241 Harmonized = Map.MapSeed;
242 foreach (KeyValuePair<int, string> P in Map.Parameters)
243 Harmonized = Harmonized.Insert(P.Key, M.Groups[P.Value]?.Value ?? string.Empty);
244
245 return true;
246 }
247 }
248 }
249 }
250
251 return false;
252 }
253
254 private class Mapping
255 {
256 public Regex Expression;
257 public string MapSeed;
258 public KeyValuePair<int, string>[] Parameters;
259 }
260
261 private class MappingExpression
262 {
263 public string Pattern;
264 public Regex Expression;
265 public string MapSeed;
266 public KeyValuePair<int, string>[] Parameters;
267 public object Tag;
268 }
269
270 private class MappingStep
271 {
272 public char Character;
273 public MappingStep[] Next;
274 public Mapping[] Expressions;
275
276 internal static MappingStep CalcStep(char Character, MappingExpression[] Expressions)
277 {
278 SortedDictionary<char, ChunkedList<MappingExpression>> Next = new SortedDictionary<char, ChunkedList<MappingExpression>>();
279 ChunkedList<Mapping> Maps = null;
280 ChunkedList<MappingStep> Steps = null;
281
282 foreach (MappingExpression Exp in Expressions)
283 {
284 if (string.IsNullOrEmpty(Exp.Pattern))
285 AddMap(ref Maps, Exp);
286 else
287 {
288 char ch = Exp.Pattern[0];
289
290 if ("\\^$.|?*+()[{".IndexOf(ch) >= 0)
291 AddMap(ref Maps, Exp);
292 else
293 {
294 if (!Next.TryGetValue(ch, out ChunkedList<MappingExpression> List))
295 {
297 Next[ch] = List;
298 }
299
300 List.Add(new MappingExpression()
301 {
302 Pattern = Exp.Pattern.Substring(1),
303 Expression = Exp.Expression,
304 MapSeed = Exp.MapSeed,
305 Parameters = Exp.Parameters,
306 Tag = Exp.Tag
307 });
308 }
309 }
310 }
311
312 foreach (KeyValuePair<char, ChunkedList<MappingExpression>> P in Next)
313 {
314 if (Steps is null)
315 Steps = new ChunkedList<MappingStep>();
316
317 Steps.Add(CalcStep(P.Key, P.Value.ToArray()));
318 }
319
320 return new MappingStep()
321 {
322 Character = Character,
323 Next = Steps?.ToArray(),
324 Expressions = Maps?.ToArray()
325 };
326 }
327
328 private static void AddMap(ref ChunkedList<Mapping> Maps, MappingExpression Exp)
329 {
330 if (Maps is null)
331 Maps = new ChunkedList<Mapping>();
332
333 Maps.Add(new Mapping()
334 {
335 Expression = Exp.Expression,
336 MapSeed = Exp.MapSeed,
337 Parameters = Exp.Parameters
338 });
339 }
340
341 public override string ToString()
342 {
343 return new string(this.Character, 1);
344 }
345 }
346 }
347}
Node referencing a chunk in a ChunkedList<T>
Definition: ChunkNode.cs:11
ChunkNode< T > Next
Next chunk
Definition: ChunkNode.cs:26
int Pos
Index after the last element in chunk.
Definition: ChunkNode.cs:51
int Start
Index of first element in chunk.
Definition: ChunkNode.cs:46
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
void Reverse()
Reverses the order of the elements in the collection.
ChunkNode< T > FirstChunk
First chunk
Definition: ChunkedList.cs:259
int IndexOf(T Item)
Determines the index of a specific item
void Add(T Item)
Adds an item to the collection.
Definition: ChunkedList.cs:272
T[] ToArray()
Returns an array containing all elements of the collection.
Maps strings of text to a harmonized set of strings using collections of regular expressions and para...
int UnregisterMappings(object Tag)
Unregisters mappings tagged with a specific object.
void RegisterMapping(string RegexPattern, string MapTo)
Registers a mapping.
bool TryMap(string InputString, out string Harmonized)
Tries to map a string using registered mappings.
void RegisterMapping(string RegexPattern, string MapTo, object Tag)
Registers a mapping.
HarmonizedTextMap()
Maps strings of text to a harmonized set of strings using collections of regular expressions and para...
bool UnregisterMapping(string RegexPattern)
Unregisters a mapping.
Represents a sub-sequence of symbols.
Definition: Step.cs:12
delegate string ToString(IElement Element)
Delegate for callback methods that convert an element value to a string.