using System.Text.RegularExpressions; namespace GsaEditor.Core.IO; /// /// Represents a single entry parsed from a .idx NML index file. /// public class GsaIndexEntry { /// /// The file alias (relative path) of the entry. /// public string Id { get; set; } = string.Empty; /// /// Compression method: 0 = raw, 1 = zlib. /// public int Method { get; set; } /// /// Original (decompressed) size in bytes. /// public uint Length { get; set; } /// /// Compressed size in bytes. /// public uint CompressedLength { get; set; } /// /// Byte offset of the data block within the archive. /// public long Offset { get; set; } } /// /// Parses .idx NML index files into a list of . /// NML is the engine's own tag syntax (<Name=value> blocks, see ), /// not standard XML. /// public static class GsaIndexReader { private static readonly Regex EntryRegex = new( @".*?)\n\s*>", RegexOptions.Singleline | RegexOptions.Compiled); private static readonly Regex TagRegex = new( @"<(?\w+)=""?(?[^"">]*)""?>", RegexOptions.Compiled); /// /// Reads index entries from the specified .idx file. /// /// The path to the .idx file. /// A list of parsed index entries. public static List Read(string filePath) { var text = File.ReadAllText(filePath); var entries = new List(); foreach (Match entryMatch in EntryRegex.Matches(text)) { var entry = new GsaIndexEntry(); foreach (Match tag in TagRegex.Matches(entryMatch.Groups["body"].Value)) { var value = tag.Groups["value"].Value; switch (tag.Groups["name"].Value) { case "ID": entry.Id = value; break; case "Method": entry.Method = value.Equals("Zlib", StringComparison.OrdinalIgnoreCase) ? 1 : 0; break; case "Len": entry.Length = uint.TryParse(value, out var l) ? l : 0; break; case "CompLen": entry.CompressedLength = uint.TryParse(value, out var cl) ? cl : 0; break; case "Offset": entry.Offset = long.TryParse(value, out var o) ? o : 0; break; } } entries.Add(entry); } return entries; } }