1
0
mirror of https://github.com/chylex/Query.git synced 2025-05-01 17:34:12 +02:00
Query/AppConv/Units/Radix.cs
2024-08-05 20:42:15 +02:00

120 lines
2.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using AppConv.General;
using AppConv.Utils;
using Base;
namespace AppConv.Units;
sealed class Radix : IUnitType {
private static readonly Dictionary<string, int> RadixDescriptions = new () {
{ "UNARY", 1 },
{ "BINARY", 2 },
{ "BIN", 2 },
{ "TERNARY", 3 },
{ "QUATERNARY", 4 },
{ "QUINARY", 5 },
{ "SENARY", 6 },
{ "OCTAL", 8 },
{ "OCT", 8 },
{ "DECIMAL", 10 },
{ "DEC", 10 },
{ "UNDECIMAL", 11 },
{ "DUODECIMAL", 12 },
{ "DOZENAL", 12 },
{ "TRIDECIMAL", 13 },
{ "TETRADECIMAL", 14 },
{ "PENTADECIMAL", 15 },
{ "HEXADECIMAL", 16 },
{ "HEX", 16 }
};
static Radix() {
for (int baseNumber = 1; baseNumber <= 16; baseNumber++) {
RadixDescriptions.Add("RADIX " + baseNumber, baseNumber);
RadixDescriptions.Add("BASE " + baseNumber, baseNumber);
}
}
public bool TryProcess(string src, string dst, out string result) {
if (!RadixDescriptions.TryGetValue(dst.ToUpperInvariant(), out int targetBase)) {
result = string.Empty;
return false;
}
if (!ParseSrc(src, out string contents, out int sourceBase)) {
result = string.Empty;
return false;
}
if (contents[0] == '-') {
throw new CommandException("Negative numbers are not supported.");
}
else if (!RadixConversion.IsBaseValid(sourceBase) || !RadixConversion.IsBaseValid(targetBase)) {
throw new CommandException("Only bases between 1 and 16 allowed.");
}
else if (!RadixConversion.IsNumberValid(contents, sourceBase)) {
throw new CommandException("The input is not a valid base " + sourceBase + " number: " + contents);
}
if (sourceBase == targetBase) {
result = src;
return true;
}
try {
result = RadixConversion.Do(contents, sourceBase, targetBase);
} catch (OverflowException) {
throw new CommandException("The number has overflown.");
}
return true;
}
private static bool ParseSrc(string src, out string sourceContent, out int sourceBase) {
if (src.All(static chr => chr is >= '0' and <= '9')) {
sourceContent = src;
sourceBase = 10;
return true;
}
string upper = src.ToUpperInvariant();
if (upper.StartsWith("0X")) {
sourceContent = upper[2..];
sourceBase = 16;
return true;
}
if (upper.StartsWith("0B")) {
sourceContent = upper[2..];
sourceBase = 2;
return true;
}
int fromIndex = src.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase);
if (fromIndex != -1) {
src = src.Remove(fromIndex, 4);
}
foreach (KeyValuePair<string, int> kvp in RadixDescriptions) {
if (src.StartsWith(kvp.Key, StringComparison.InvariantCultureIgnoreCase)) {
sourceContent = src[kvp.Key.Length..].Trim();
sourceBase = kvp.Value;
return true;
}
else if (src.EndsWith(kvp.Key, StringComparison.InvariantCultureIgnoreCase)) {
sourceContent = src[..^kvp.Key.Length].Trim();
sourceBase = kvp.Value;
return true;
}
}
sourceContent = string.Empty;
sourceBase = 0;
return false;
}
}