Nuke.Unreal
Build Unreal apps in Style.
Loading...
Searching...
No Matches
ConfigIni.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text.RegularExpressions;
5
6namespace Nuke.Unreal.Ini;
7
8/// <summary>
9/// Utilities for parsing Unreal configuration files
10/// </summary>
11public static class ConfigCommon
12{
13 public static GroupCollection? MatchGroup(
14 this string text,
15 string pattern,
16 RegexOptions options = RegexOptions.CultureInvariant | RegexOptions.Multiline)
17 {
18 var match = Regex.Match(text, pattern, options);
19 return match?.Groups;
20 }
21
22 public static GroupCollection? Fetch(this GroupCollection groups, string capturename, out string result)
23 {
24 result = groups[capturename].Value;
25 return groups;
26 }
27
28 /// <summary>
29 /// Convert a command type into its representing character
30 /// </summary>
31 /// <param name="commandType"></param>
32 /// <returns>
33 /// Command type character or empty string if command doesn't have associated symbol.
34 /// </returns>
35 public static string AsCharacter(this CommandType commandType) => commandType switch
36 {
37 CommandType.Set => "",
38 CommandType.Add => "+",
39 CommandType.Remove => "-",
40 CommandType.Clear => "!",
41 CommandType.Comment => ";",
42 _ => ""
43 };
44}
45
46/// <summary>
47/// The root class representing Unreal INI configuration
48/// </summary>
49public class ConfigIni
50{
51 /// <summary>
52 /// Sections separated by `[SectionName]` syntax
53 /// </summary>
54 public readonly Dictionary<string, ConfigSection> Sections = new();
55
56 /// <summary>
57 /// Get a section via its name
58 /// </summary>
59 public ConfigSection? this[string key] => Sections.ContainsKey(key) ? Sections[key] : null;
60
61 /// <summary>
62 /// Get an existing section or add it if it doesn't exist yet.
63 /// </summary>
64 /// <param name="key"></param>
65 /// <returns></returns>
66 public ConfigSection FindOrAdd(string key)
67 {
68 var result = this[key];
69 if (result == null)
70 {
71 var lastOrder = Sections.Count > 0 ? Sections.Values.Max(s => s.Order) + 1 : 0;
72 result = new ConfigSection {Order = lastOrder, Name = key};
73 Sections.Add(key, result);
74 }
75 return result;
76 }
77
78 /// <summary>
79 /// Parse an Unreal configuration text into a ConfigIni.
80 /// </summary>
81 /// <returns>Resulting ConfigIni or null if parsing was not possible.</returns>
82 public static ConfigIni? Parse(string? input)
83 {
84 if (string.IsNullOrWhiteSpace(input)) return null;
85 ConfigSection? currentSection = null;
86 var ini = new ConfigIni();
87 int order = 0;
88 foreach(var lineIn in input!.Split(new [] { "\r", "\n" }, StringSplitOptions.None))
89 {
90 if (string.IsNullOrWhiteSpace(lineIn)) continue;
91 var line = lineIn.Trim();
92
93 if (line.StartsWith("[") && line.EndsWith("]"))
94 {
95 var sectionName = line.TrimStart('[').TrimEnd(']');
96 if (ini.Sections.ContainsKey(sectionName))
97 {
98 currentSection = ini.Sections[sectionName];
99 }
100 else
101 {
102 currentSection = new() { Order = order, Name = sectionName };
103 ini.Sections.Add(sectionName, currentSection);
104 }
105 }
106 else
107 {
108 currentSection?.SetLine(line, order);
109 }
110 order++;
111 }
112
113 return order > 0 ? ini : null;
114 }
115
116 /// <summary>
117 /// Compose another ConfigIni instance into this one, overriding existing values and adding new
118 /// ones.
119 /// </summary>
120 public void Merge(ConfigIni from)
121 {
122 foreach(var fromSection in from.Sections.Values)
123 {
124 var name = fromSection.Name ?? "";
125 if (Sections.ContainsKey(name))
126 {
127 Sections[name].Merge(fromSection);
128 }
129 else
130 {
131 Sections.Add(name, fromSection.Copy());
132 }
133 }
134 }
135
136 /// <summary>
137 /// Convert this ConfigIni back to something Unreal can read.
138 /// </summary>
139 public string Serialize() => string.Join(Environment.NewLine,
140 Sections.Values.OrderBy(s => s.Order).Select(s => s.Serialize())
141 );
142}
Utilities for parsing Unreal configuration files.
Definition ConfigIni.cs:12
static string AsCharacter(this CommandType commandType)
Convert a command type into its representing character.
The root class representing Unreal INI configuration.
Definition ConfigIni.cs:50
readonly Dictionary< string, ConfigSection > Sections
Sections separated by [SectionName] syntax.
Definition ConfigIni.cs:54
string Serialize()
Convert this ConfigIni back to something Unreal can read.
void Merge(ConfigIni from)
Compose another ConfigIni instance into this one, overriding existing values and adding new ones.
Definition ConfigIni.cs:120
ConfigSection FindOrAdd(string key)
Get an existing section or add it if it doesn't exist yet.
Definition ConfigIni.cs:66
static ? ConfigIni Parse(string? input)
Parse an Unreal configuration text into a ConfigIni.
Definition ConfigIni.cs:82
Represents a section block in an Unreal INI configuration under a [SectionName] header.
CommandType
Unreal INI config items are read top to bottom, reading like individual commands, especially when man...