Able
Askowl Base Library Enabler
Template.cs
1 // Copyright 2019 (C) paul@marrington.net http://www.askowl.net/unity-packages
2 
3 using System;
4 using System.Collections.Generic;
5 using System.Text;
6 using System.Text.RegularExpressions;
7 
8 namespace Askowl {
9  /// <a href=""></a> //#TBD#//
10  public class Template : IDisposable {
11  /// <a href=""></a> //#TBD#//
12  protected string result = "";
13 
14  /// <a href=""></a> //#TBD#//
15  public static Template Instance => Cache<Template>.Instance;
16 
17  /// <a href=""></a> //#TBD#//
18  public struct Substitution {
19  /// <a href=""></a> //#TBD#//
20  public Regex Regex;
21  /// <a href=""></a> //#TBD#//
22  public string With;
23  }
24 
25  /// <a href=""></a> //#TBD#//
26  public List<Substitution> substitutions = new List<Substitution>();
27 
28  /// <a href=""></a> //#TBD#//
29  public Template From(string text) {
30  result = text;
31  return this;
32  }
33 
34  /// <a href=""></a> //#TBD#//
35  public Template Substitute(string regex, string with) =>
36  Substitute(new Regex(regex, RegexOptions.Singleline), with);
37 
38  /// <a href=""></a> //#TBD#//
39  public Template Substitute(Regex regex, string with) {
40  substitutions.Add(new Substitution {Regex = regex, With = with});
41  return this;
42  }
43 
44  /// <a href=""></a> //#TBD#//
45  public Template Substitute(string regex, object with) => Substitute(regex, with.ToString());
46 
47  /// <a href=""></a> //#TBD#//
48  public Template Substitute(Regex regex, object with) => Substitute(regex, with.ToString());
49 
50  /// <a href=""></a> //#TBD#//
51  public Template And(string regex, string with) => Substitute(regex, with);
52 
53  /// <a href=""></a> //#TBD#//
54  public Template And(string regex, object with) => Substitute(regex, with);
55 
56  /// <a href=""></a> //#TBD#//
57  public Template And(Regex regex, string with) => Substitute(regex, with);
58 
59  /// <a href=""></a> //#TBD#//
60  public Template And(Regex regex, object with) => Substitute(regex, with);
61 
62  /// <a href=""></a> //#TBD#//
63  public string Result() {
64  if (string.IsNullOrWhiteSpace(result)) return "";
65  for (int i = 0; i < substitutions.Count; i++) {
66  result = substitutions[i].Regex.Replace(result, substitutions[i].With);
67  }
68  return result;
69  }
70 
71  /// <a href=""></a> //#TBD#//
72  public virtual void Add() { }
73 
74  /// <a href=""></a> //#TBD#//
75  public virtual bool More() => false;
76 
77  /// <inheritdoc />
78  public virtual void Dispose() {
79  substitutions.Clear();
80  result = "";
81  Cache<Template>.Dispose(this);
82  }
83 
84  #region Inner Template
85  private class InnerTemplate : Template {
86  internal Regex regex;
87  private string template;
88  private readonly StringBuilder builder = new StringBuilder();
89  internal Template parent;
90  internal readonly List<(int left, int right, string value)> matches =
91  new List<(int left, int right, string value)>();
92  internal int match;
93 
94  public override void Add() {
95  builder.Append(From(template).Result());
96  substitutions.Clear();
97  }
98 
99  public override bool More() {
100  if (match < matches.Count) {
101  var left = parent.result.Substring(0, matches[match].left);
102  var right = parent.result.Substring(matches[match].right);
103  parent.result = $"{left}{builder}{right}";
104  builder.Clear();
105  }
106  if (--match < 0) return false;
107  template = matches[match].value;
108  return true;
109  }
110 
111  public override void Dispose() {
112  if (!string.IsNullOrWhiteSpace(result)) parent.result = regex.Replace(parent.result, result);
113  base.Dispose();
114  }
115  }
116  /// <a href=""></a> //#TBD#//
117  public Template Inner(Regex regex) {
118  var inner = Cache<InnerTemplate>.Instance;
119  inner.parent = this;
120  inner.regex = regex;
121 
122  inner.matches.Clear();
123  for (var match = regex.Match(result); match.Success; match = match.NextMatch())
124  if (match.Groups.Count >= 2)
125  inner.matches.Add((match.Index, match.Index + match.Length, match.Groups[1].Value));
126  inner.match = inner.matches.Count;
127  return inner;
128  }
129  /// <a href=""></a> //#TBD#//
130  public Template Inner(string regex) => Inner(new Regex(regex, RegexOptions.Singleline));
131  #endregion
132  }
133 }
Definition: Clock.cs:3
Instance caching
Definition: Cache.cs:9
Regex Regex
//#TBD#//
Definition: Template.cs:20
virtual void Add()
//#TBD#//
Definition: Template.cs:72
string With
//#TBD#//
Definition: Template.cs:22
virtual bool More()
//#TBD#//
Template Inner(Regex regex)
//#TBD#//
Definition: Template.cs:117
Template And(string regex, string with)
//#TBD#//
string result
//#TBD#//
Definition: Template.cs:12
List< Substitution > substitutions
//#TBD#//
Definition: Template.cs:26
string Result()
//#TBD#//
Definition: Template.cs:63
virtual void Dispose()
Definition: Template.cs:78
static Template Instance
//#TBD#//
Definition: Template.cs:15
//#TBD#//
Definition: Template.cs:10
Template Substitute(Regex regex, string with)
//#TBD#//
Definition: Template.cs:39
Template Substitute(string regex, string with)
//#TBD#//
Template From(string text)
//#TBD#//
Definition: Template.cs:29