ErrorsManager/CSharp/ErrorsManager.cs

626 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ErrorsManager{
public class ErrorsManager{
public static readonly char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".ToCharArray();
public static readonly string[] ERRORS_MESSAGES = new string[]{
"invalid_alphabet",
"invalid_base",
"invalid_alphabet_type",
"too_short_alphabet",
"repeated_characters_in_alphabet",
"too_long_alphabet",
"base_lower_than_2",
"base_greater_than_128",
"base_greater_than_alphabet"
};
public static readonly Regex RE_KEY = new Regex(@"^[a-z_][a-z0-9_]*$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private int error = 0;
private char[] alphabet = new char[0];
private Dictionary<char, byte> dictionary = new Dictionary<char, byte>();
private byte _base;
private byte power;
public ErrorsManager(object inputs = null){
set_alphabet(
get<object>("alphabet", inputs, ALPHABET),
get<int>("base", inputs, 64)
);
}
public int set_alphabet(object alphabet = null, int _base = 64){
int original_length;
error = 0;
if(alphabet == null)
this.alphabet = ALPHABET;
else if(alphabet is string alphabet_string)
this.alphabet = alphabet_string.ToCharArray();
else if(alphabet is IEnumerable<char> alphabet_enumerable)
this.alphabet = alphabet_enumerable.ToArray<char>();
else{
error |= 1 << 2;
this.alphabet = ALPHABET;
}
original_length = this.alphabet.Length;
this.alphabet = this.alphabet.Distinct<char>().ToArray<char>();
if(this.alphabet.Length < 2){
error |= 1 << 3;
this.alphabet = ALPHABET;
}
if(this.alphabet.Length != original_length)
error |= 1 << 4;
if(this.alphabet.Length > 128)
error |= 1 << 5;
error |= (
_base < 2 ? 1 << 0 :
_base > 128 ? 1 << 1 :
_base >= this.alphabet.Length ? 1 << 2 :
0) << 6;
if(error >> 6 == 0)
this.alphabet = this.alphabet.Take(_base).ToArray<char>();
this.alphabet = this.alphabet.Take(
this._base = (byte)Math.Pow(2,
power = (byte)Math.Log2(this.alphabet.Take(128).Count<char>())
)
).ToArray<char>();
dictionary.Clear();
for(byte i = 0; i < this.alphabet.Length; i ++)
dictionary[this.alphabet[i]] = i;
return error;
}
public string get_alphabet(){
return new string(alphabet);
}
public byte[] to_array(string code){
return code.Select<char, byte>(character => dictionary[character]).ToArray<byte>();
}
public byte[] to_array(byte[] code){
return code;
}
public byte[] to_array(int code){
List<byte> hexas = new List<byte>();
while(code != 0){
hexas.Add((byte)(code % _base));
code /= _base;
}
return hexas.ToArray<byte>();
}
public string to_string(byte[] code){
return new string(code.Select<byte, char>(value => alphabet[value]).ToArray<char>());
}
public string to_string(int code){
StringBuilder hexas = new StringBuilder();
while(code != 0){
hexas.Append(alphabet[(byte)(code % _base)]);
code /= _base;
}
return hexas.ToString();
}
public string to_string(string code){
return code;
}
public int to_integer(string code){
int _string = 0;
for(int i = code.Length - 1; i >= 0; i --)
_string = _string * _base + dictionary[code[i]];
return _string;
}
public int to_integer(byte[] code){
int array = 0;
for(int i = code.Length - 1; i >= 0; i --)
array = array * _base + code[i];
return array;
}
public int to_integer(int code){
return code;
}
public string to_string_binary(string code){
return string.Join("", code.Reverse<char>().Select<char, string>(character => Convert.ToString(dictionary[character], 2).PadLeft(power, '0')));
}
public string to_string_binary(byte[] code){
return string.Join("", code.Reverse<byte>().Select<byte, string>(hexa => Convert.ToString(hexa, 2).PadLeft(power, '0')));
}
public string to_string_binary(int code){
string binary = Convert.ToString(code, 2);
int remainer = binary.Length % power;
return (
remainer == 0 ? binary :
binary.PadLeft(binary.Length + power - remainer, '0'));
}
public int get_bits(string code){
return code.Length == 0 ? 0 : (code.Length - 1) * power + (int)Math.Ceiling(Math.Log2(dictionary[code.Last<char>()] + 1));
}
public int get_bits(byte[] code){
return code.Length == 0 ? 0 : (code.Length - 1) * power + (int)Math.Ceiling(Math.Log2(code.Last<byte>() + 1));
}
public int get_bits(int code){
return (int)Math.Ceiling(Math.Log2(code + 1));
}
public void get_from_bits(string code, ref int from, ref int bits){
get_from_bits(to_array(code), ref from, ref bits);
}
public void get_from_bits(byte[] code, ref int from, ref int bits){
if(from < 0){
from = get_bits(code) + from;
if(from < 0)
from = 0;
}
if(bits < 0){
from += bits;
bits *= -1;
if(from < 0){
bits += from;
from = 0;
}
}
}
public void get_from_bits(int code, ref int from, ref int bits){
get_from_bits(to_array(code), ref from, ref bits);
}
public string clean(string code){
int l = code.Length;
while(l > 0 && code[l - 1] == alphabet[0])
l --;
return (
code.Length == l ? code :
l == 0 ? alphabet[0].ToString() :
code.Substring(0, l));
}
public byte[] clean(byte[] code){
int l = code.Length;
while(l > 0 && code[l - 1] == 0)
l --;
return (
l == code.Length ? code :
l == 0 ? new byte[]{0} :
code.Take(l).ToArray<byte>());
}
public int clean(int code){
return code;
}
public string get_range(string code, int from, int bits = 0){
return to_string(get_range(to_array(code), from, bits));
}
public byte[] get_range(byte[] code, int from, int bits = 0){
List<byte> hexas;
get_from_bits(code, ref from, ref bits);
if(bits == 0)
bits = get_bits(code) - from;
if(bits <= 0)
return new byte[]{0};
hexas = code.ToList<byte>();
if(from > 0){
byte shift = (byte)(from % power);
int mask = ~-_base;
hexas = hexas.Skip(from / power).ToList<byte>();
if(shift != 0 && hexas.Count > 0){
int l = hexas.Count - 1;
for(int i = 0; i < l; i ++)
hexas[i] = (byte)((hexas[i] >> shift) | ((hexas[i + 1] << (power - shift)) & mask));
hexas[l] >>= shift;
}
}
if(bits > 0){
byte shift = (byte)(bits % power);
hexas = hexas.Take<byte>((int)Math.Ceiling(bits / (double)power)).ToList<byte>();
if(shift != 0 && hexas.Count > 0)
hexas[hexas.Count - 1] &= (byte)((1 << shift) - 1);
}
return clean(hexas.ToArray<byte>());
}
public int get_range(int code, int from, int bits = 0){
get_from_bits(code, ref from, ref bits);
if(from > 0)
code = (code >> from) & ((1 << (31 - from)) - 1);
if(bits <= 0 || bits >= 31)
return code;
if(from + bits > 31)
bits = 31 - from;
return code & ((1 << bits) - 1);
}
public (int, string)[] process(string code, IEnumerable<string> messages){
return process(to_array(code), messages);
}
public (int, string)[] process(byte[] code, IEnumerable<string> messages, Dictionary<int, int>? blocks = null){
List<(int, string)> response = new List<(int, string)>();
int k = 0;
if(blocks == null)
blocks = new Dictionary<int, int>();
for(int i = 0, l = code.Length * power; i < l;)
if(blocks.ContainsKey(i) && blocks[i] > 0){
int logarithm = (int)Math.Ceiling(Math.Log2(blocks[i]));
int _k = to_integer(get_range(code, i, logarithm == 0 ? logarithm = 1 : logarithm));
if(_k > 0){
_k = k + _k;
response.Add((_k, messages.ElementAtOrDefault(_k) ?? "error_message_" + _k.ToString()));
}
k += blocks[i];
i += logarithm;
}else{
if((code[i / power] & (1 << i % power)) != 0)
response.Add((k, messages.ElementAtOrDefault(k) ?? "error_message_" + k.ToString()));
k ++;
i ++;
}
return response.ToArray<(int, string)>();
}
public (int, string)[] process(int code, IEnumerable<string> messages){
return process(to_array(code), messages);
}
public string bitwise(string code, int bits){
return to_string(bitwise(to_array(code), bits));
}
public byte[] bitwise(byte[] code, int bits){
if(code.Length == 0 || bits == 0)
return code;
byte shift = (byte)(Math.Abs(bits) % power);
int mask = _base - 1;
List<byte> hexas = code.ToList<byte>();
if(bits < 0){
hexas.RemoveRange(0, (int)(-bits / power));
if(shift != 0 && hexas.Count != 0){
int l = hexas.Count - 1;
for(int i = 0; i < l; i ++)
hexas[i] = (byte)((hexas[i] >> shift) | ((hexas[i + 1] << (power - shift)) & mask));
hexas[hexas.Count - 1] >>= shift;
}
}else{
if(shift != 0){
int last_hexa = hexas[hexas.Count - 1] << shift;
for(int i = hexas.Count - 1; i > 0; i --)
hexas[i] = (byte)(((hexas[i] << shift) & mask) | (hexas[i - 1] >> (power - shift)));
hexas[0] = (byte)((hexas[0] << shift) & mask);
if(last_hexa >= _base)
hexas.Add((byte)(last_hexa >> power));
}
for(int i = bits / power; i > 0; i --)
hexas.Insert(0, 0);
}
return clean(hexas.ToArray<byte>());
}
public int bitwise(int code, int bits){
return (
bits > 0 ? code << bits :
bits < 0 ? code >> -bits :
code);
}
public string reset(string code, int from, int bits = 0, bool reversed = false){
return to_string(reset(to_array(code), from, bits, reversed));
}
public byte[] reset(byte[] code, int from, int bits = 0, bool reversed = false){
List<byte> hexas = code.ToList<byte>();
int hexa_from;
int hexa_to;
int l;
byte from_mask;
byte to_mask;
get_from_bits(code, ref from, ref bits);
hexa_from = (int)(from / power);
hexa_to = (int)((from + bits) / power);
if(reversed){
l = from % power;
from_mask = (byte)(~-(1 << power - l) << l);
to_mask = (byte)~-(1 << (from + bits) % power);
for(int i = 0; i < hexas.Count; i ++)
if(i < hexa_from || i > hexa_to)
hexas[i] = 0;
if(hexa_from == hexa_to)
hexas[hexa_to] &= (byte)(from_mask & to_mask);
else{
hexas[hexa_from] &= from_mask;
if(hexa_to < hexas.Count)
hexas[hexa_to] &= to_mask;
}
}else{
l = (from + bits) % power;
from_mask = (byte)~-(1 << (from % power));
to_mask = (byte)(~-(1 << power - l) << l);
if(hexa_from == hexa_to){
hexas[hexa_to] &= (byte)(from_mask | to_mask);
}else{
hexas[hexa_from] &= from_mask;
for(int i = hexa_from + 1; i < hexa_to && i < hexas.Count; i ++)
hexas[i] = 0;
if(hexa_to < hexas.Count)
hexas[hexa_to] &= to_mask;
}
}
return clean(hexas.ToArray<byte>());
}
public int reset(int code, int from, int bits = 0, bool reversed = false){
get_from_bits(code, ref from, ref bits);
if(from + bits > 31)
bits = 31 - from;
return code & (reversed ?
~-(1 << bits) << from :
(~-(1 << get_bits(code)) << from + bits) | ~-(1 << from));
}
public bool has(string code, int from = 0, int bits = 0){
foreach(char character in get_range(code, from, bits))
if(character != alphabet[0])
return true;
return false;
}
public bool has(byte[] code, int from = 0, int bits = 0){
foreach(byte hexa in get_range(code, from, bits))
if(hexa != 0)
return true;
return false;
}
public bool has(int code, int from = 0, int bits = 0){
return get_range(code, from, bits) != 0;
}
public string set(string error, string code, int _from = 0, int bits = 0){
return to_string(set(to_array(error), to_array(code), _from, bits));
}
public string set(string error, byte[] code, int _from = 0, int bits = 0){
return to_string(set(to_array(error), code, _from, bits));
}
public string set(string error, int code, int _from = 0, int bits = 0){
return to_string(set(to_array(error), to_array(code), _from, bits));
}
public byte[] set(byte[] error, string code, int _from = 0, int bits = 0){
return set(error, to_array(code), _from, bits);
}
public byte[] set(byte[] error, byte[] code, int _from = 0, int bits = 0){
int l;
int m = error.Length;
int n = code.Length;
List<byte> results = new List<byte>();
if(bits != 0)
m = (error = reset(error, _from, bits)).Length;
if(_from != 0)
n = (code = bitwise(code, _from)).Length;
l = m > n ? m : n;
for(int i = 0; i < l; i ++)
results.Add((byte)(
(i < m ? error[i] : (byte)0) |
(i < n ? code[i] : (byte)0)
));
return clean(results.ToArray<byte>());
}
public byte[] set(byte[] error, int code, int _from = 0, int bits = 0){
return set(error, to_array(code), _from, bits);
}
public int set(int error, string code, int _from = 0, int bits = 0){
return to_integer(set(error, to_integer(code), _from, bits));
}
public int set(int error, byte[] code, int _from = 0, int bits = 0){
return to_integer(set(error, to_integer(code), _from, bits));
}
public int set(int error, int code, int _from = 0, int bits = 0){
if(bits != 0)
error = reset(error, _from, bits);
if(_from != 0)
code = bitwise(code, _from);
return error | code;
}
public static List<string> get_keys(object items){
List<string> keys = new List<string>();
if(items is string item_string){
if(RE_KEY.IsMatch(item_string))
keys.Add(item_string);
}else if(items is IEnumerable<string> strings){
foreach(string item_i in strings)
if(!keys.Contains(item_i) && RE_KEY.IsMatch(item_i))
keys.Add(item_i);
}else if(items is IEnumerable<object> list)
foreach(object item in list){
if(item == null)
continue;
if(item is string string_item){
if(!keys.Contains(string_item) && RE_KEY.IsMatch(string_item))
keys.Add(string_item);
}else
foreach(string key in get_keys(item))
if(!keys.Contains(key) && RE_KEY.IsMatch(key))
keys.Add(key);
}
return keys;
}
public static List<Dictionary<string, object>> get_dictionaries(object items){
List<Dictionary<string, object>> dictionaries = new List<Dictionary<string, object>>();
if(items is Dictionary<string, object> dictionary)
dictionaries.Add(dictionary);
else if(items is IEnumerable<object> list)
foreach(object item in list)
dictionaries.AddRange(get_dictionaries(item));
return dictionaries;
}
public static T get<T>(object keys, object inputs, T _default = default(T)){
List<string> keys_list = get_keys(keys);
if(keys_list.Count != 0)
foreach(Dictionary<string, object> dictionary in get_dictionaries(inputs))
foreach(string key in keys_list)
if(dictionary.TryGetValue(key, out object value) && value is T typed)
return typed;
return _default;
}
public static T[] unique<T>(IEnumerable<T> items){
return items.Distinct<T>().ToArray<T>();
}
public static bool is_string(object value){
return value is string;
}
public static bool is_array(object value){
return value is byte[];
}
public static bool is_integer(object value){
return value is int;
}
public static void for_each_enumerate<T>(IEnumerable<T> items, Action<T, int> action){
int i = 0;
foreach(T item in items)
action(item, i ++);
}
}
}