Files
AohDrllTools/DrillTapeParameterCleaner.cs

156 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace DrillTools
{
internal static class DrillTapeParameterCleaner
{
private const int Gb2312CodePage = 936;
private static readonly char[] LineEndChars = { '\r', '\n' };
private static readonly Regex HeaderToolDefinitionStartPattern = new(
@"^T\d+C",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex ToolDefinitionPattern = new(
@"^(?<prefix>\s*T\d+C\d+(?:\.\d+)?)(?<parameters>H.+)$",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static bool CanClearParameters(string drillTapeContent)
{
var lines = SplitLines(drillTapeContent);
if (lines.Count < 2)
return false;
string secondLine = lines[1].Text.Trim();
if (!secondLine.StartsWith(";") || secondLine.Length == 1)
return false;
var toolDefinitionLines = GetHeaderToolDefinitionLines(lines);
if (toolDefinitionLines.Count == 0)
return false;
foreach (var line in toolDefinitionLines)
{
if (!ToolDefinitionPattern.IsMatch(line.Text.TrimEnd()))
return false;
}
return true;
}
public static string ClearParameters(string drillTapeContent)
{
if (!CanClearParameters(drillTapeContent))
throw new InvalidOperationException("钻带文件不符合清空参数条件");
var lines = SplitLines(drillTapeContent);
var builder = new StringBuilder(drillTapeContent.Length);
for (int i = 0; i < lines.Count; i++)
{
if (i == 1)
continue;
string text = lines[i].Text;
var match = ToolDefinitionPattern.Match(text.TrimEnd());
if (match.Success && IsBeforeHeaderEnd(lines, i))
{
int trailingWhitespaceLength = text.Length - text.TrimEnd().Length;
string trailingWhitespace = trailingWhitespaceLength > 0 ? text[^trailingWhitespaceLength..] : string.Empty;
text = match.Groups["prefix"].Value + trailingWhitespace;
}
builder.Append(text);
builder.Append(lines[i].LineEnding);
}
return builder.ToString();
}
public static void ClearParametersAndSave(string filePath)
{
string content = CommandTypeFileReader.ReadAllText(filePath);
string cleanedContent = ClearParameters(content);
string backupFilePath = filePath + ".bak";
File.Copy(filePath, backupFilePath, true);
using var writer = new StreamWriter(filePath, false, CreateAnsiEncoding());
writer.Write(cleanedContent);
}
private static List<DrillTapeLine> SplitLines(string content)
{
var lines = new List<DrillTapeLine>();
int index = 0;
while (index < content.Length)
{
int lineEndIndex = content.IndexOfAny(LineEndChars, index);
if (lineEndIndex < 0)
{
lines.Add(new DrillTapeLine(content[index..], string.Empty));
return lines;
}
string text = content[index..lineEndIndex];
string lineEnding;
if (content[lineEndIndex] == '\r' && lineEndIndex + 1 < content.Length && content[lineEndIndex + 1] == '\n')
{
lineEnding = "\r\n";
index = lineEndIndex + 2;
}
else
{
lineEnding = content[lineEndIndex].ToString();
index = lineEndIndex + 1;
}
lines.Add(new DrillTapeLine(text, lineEnding));
}
if (content.Length == 0)
lines.Add(new DrillTapeLine(string.Empty, string.Empty));
return lines;
}
private static List<DrillTapeLine> GetHeaderToolDefinitionLines(IReadOnlyList<DrillTapeLine> lines)
{
var toolDefinitionLines = new List<DrillTapeLine>();
foreach (var line in lines)
{
string trimmedLine = line.Text.Trim();
if (trimmedLine == "%")
break;
if (HeaderToolDefinitionStartPattern.IsMatch(trimmedLine))
toolDefinitionLines.Add(line);
}
return toolDefinitionLines;
}
private static bool IsBeforeHeaderEnd(IReadOnlyList<DrillTapeLine> lines, int lineIndex)
{
for (int i = 0; i < lineIndex; i++)
{
if (lines[i].Text.Trim() == "%")
return false;
}
return true;
}
private static Encoding CreateAnsiEncoding()
{
return Encoding.GetEncoding(Gb2312CodePage);
}
private readonly record struct DrillTapeLine(string Text, string LineEnding);
}
}