mirror of
https://github.com/chylex/Query.git
synced 2025-05-01 17:34:12 +02:00
120 lines
2.9 KiB
C#
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;
|
|
}
|
|
}
|