Imports System Imports System.Collections.Generic Imports System.Text Imports System.Text.RegularExpressions Imports System.Linq Namespace ErrorsManager Public Class ErrorsManager Public Shared ReadOnly ALPHABET As Char() = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/=".ToCharArray() Public Shared ReadOnly ERRORS_MESSAGES As String() = 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 Shared ReadOnly RE_KEY As New Regex("^[a-zA-Z0-9_]+$", RegexOptions.IgnoreCase Or RegexOptions.Compiled) Private _error As Integer = 0 Private _alphabet As Char() = New Char(){} Private dictionary As New Dictionary(Of Char, Byte)() Private _base As Byte Private power As Byte Public Sub New(Optional inputs As Object = Nothing) set_alphabet( ErrorsManager.[get](Of Object)("alphabet", inputs, ALPHABET), ErrorsManager.[get](Of Integer)("base", inputs, 64) ) end Sub Public Function set_alphabet(alphabet As Object, Optional _base As Integer = 64) As Integer Dim original_length As Integer _error = 0 If alphabet Is Nothing Then _alphabet = ALPHABET ElseIf TypeOf alphabet Is String Then _alphabet = DirectCast(alphabet, String).ToCharArray() ElseIf TypeOf alphabet Is IEnumerable(Of Char) Then _alphabet = DirectCast(alphabet, IEnumerable(Of Char)).ToArray() Else _error = _error Or (1 << 0) Return _error End If original_length = _alphabet.Length _alphabet = _alphabet.Distinct().ToArray() If _alphabet.Length < 2 Then _error = _error Or (1 << 3) _alphabet = ALPHABET End If If _alphabet.Length <> original_length Then _error = _error Or (1 << 4) If _alphabet.Length > 128 Then _error = _error Or (1 << 5) _error = _error Or ( If(_base < 2, 1 << 0, If(_base > 128, 1 << 1, If(_base > _alphabet.Length, 1 << 2, 0)))) << 6 If (_error >> 6) = 0 Then _alphabet = _alphabet.Take(_base).ToArray() power = CByte(Math.Truncate(Math.Log(_alphabet.Take(128).Count(), 2))) Me._base = CByte(Math.Truncate(Math.Pow(2, power))) _alphabet = _alphabet.Take(Me._base).ToArray() dictionary.Clear() For i As Byte = 0 To _alphabet.Length - 1 dictionary(_alphabet(i)) = i Next Return _error End Function Public Function get_alphabet() As String Return New String(_alphabet) End Function Public Function to_array(code As String) As Byte() Return code.Select(Function(character) dictionary(character)).ToArray() End Function Public Function to_array(code As Byte()) As Byte() Return code End Function Public Function to_array(code As Integer) As Byte() Dim hexas As New List(Of Byte)() While code > 0 hexas.Add(CByte(code Mod _base)) code \= _base End While Return hexas.ToArray() End Function Public Function to_string(code As Byte()) As String Return New String(code.Select(Function(hexa) _alphabet(hexa)).ToArray()) End Function Public Function to_string(code As Integer) As String Dim hexas As New StringBuilder() While code > 0 hexas.Append(_alphabet(code Mod _base)) code \= _base End While Return hexas.ToString() End Function Public Function to_string(code As String) As String Return code End Function Public Function to_integer(code As Byte()) As Integer Dim _integer As Integer = 0 For i As Integer = code.Length - 1 To 0 Step -1 _integer = _integer * _base + code(i) Next Return _integer End Function Public Function to_integer(code As String) As Integer Dim _integer As Integer = 0 For i As Integer = code.Length - 1 To 0 Step -1 _integer = _integer * _base + dictionary(code(i)) Next Return _integer End Function Public Function to_integer(code As Integer) As Integer Return code End Function Public Function to_string_binary(code As Byte()) As String Return String.Concat(code.Reverse().Select(Function(hexa) Convert.ToString(hexa, 2).PadLeft(power, "0"c))) End Function Public Function to_string_binary(code As Integer) As String Dim binary As String = Convert.ToString(code, 2) Dim remainer As Integer = binary.Length Mod power Return If(remainer = 0, binary, binary.PadLeft(binary.Length + power - remainer, "0"c)) End Function Public Function to_string_binary(code As String) As String Return String.Concat(code.Reverse().Select(Function(character) Convert.ToString(dictionary(character), 2).PadLeft(power, "0"c))) End Function Public Function get_bits(code As String) As Integer Return If(code.Length = 0, 0, (code.Length - 1) * power + CInt(Math.Ceiling(Math.Log(dictionary(code.Last()) + 1, 2)))) End Function Public Function get_bits(code As Byte()) As Integer Return If(code.Length = 0, 0, (code.Length - 1) * power + CInt(Math.Ceiling(Math.Log(code.Last() + 1, 2)))) End Function Public Function get_bits(code As Integer) As Integer Return CInt(Math.Ceiling(Math.Log(code + 1, 2))) End Function Public Sub get_from_bits(code As String, ByRef [from] As Integer, ByRef bits As Integer) get_from_bits(to_array(code), from, bits) End Sub Public Sub get_from_bits(code As Byte(), ByRef [from] As Integer, ByRef bits As Integer) If [from] < 0 Then [from] = get_bits(code) + from If [from] < 0 Then [from] = 0 End If If bits < 0 Then [from] += bits bits *= -1 If [from] < 0 Then bits += [from] [from] = 0 End If End If End Sub Public Sub get_from_bits(code As Integer, ByRef [from] As Integer, ByRef bits As Integer) get_from_bits(to_array(code), [from], bits) End Sub Public Function clean(code As String) As String Dim l As Integer = code.Length While l > 0 AndAlso code(l - 1) = _alphabet(0) l -= 1 End While Return ( If(code.Length = l, code, If(l = 0, _alphabet(0).ToString(), code.Substring(0, l)))) End Function Public Function clean(code As Byte()) As Byte() Dim l As Integer = code.Length While l > 0 AndAlso code(l - 1) = 0 l -= 1 End While Return ( If(code.Length = l, code, If(l = 0, New Byte(){0}, code.Take(l).ToArray()))) End Function Public Function clean(code As Integer) As Integer Return code End Function Public Function get_range(code As String, [from] As Integer, bits As Integer) As String Return to_string(get_range(to_array(code), [from], bits)) End Function Public Function get_range(code As Byte(), [from] As Integer, bits As Integer) As Byte() Dim hexas As List(Of Byte) get_from_bits(code, [from], bits) If bits = 0 Then bits = get_bits(code) - [from] If bits <= 0 Then Return New Byte(){} hexas = code.ToList() If [from] > 0 Then Dim shift As Byte = CByte([from] Mod power) Dim mask As Integer = CInt((1 << shift) - 1) hexas = hexas.Skip([from] \ power).ToList() If shift <> 0 AndAlso hexas.Count() > 0 Then Dim l = hexas.Count() - 2 For i As Integer = 0 To l hexas(i) = CByte((hexas(i) >> shift) Or ((hexas(i + 1) << (power - shift)) And mask)) Next hexas(l + 1) = CByte(hexas(l + 1) >> shift) End If End If If bits > 0 Then Dim shift As Byte = CByte(bits Mod power) hexas = hexas.Take(CInt(Math.Ceiling(bits / CDbl(power)))).ToList() If shift <> 0 AndAlso hexas.Count() > 0 Then hexas(hexas.Count() - 1) = CByte(hexas.Last() And ((1 << shift) - 1)) End If End If Return clean(hexas.ToArray()) End Function Public Function get_range(code As Integer, [from] As Integer, bits As Integer) As Integer get_from_bits(code, [from], bits) If [from] > 0 Then code = (code >> [from]) And ((1 << (31 - [from])) - 1) If bits <= 0 OrElse bits >= 31 Then Return code If [from] + bits > 31 Then bits = 31 - [from] Return code And ((1 << bits) - 1) End Function Public Function process(code As String, messages As IEnumerable(Of String), Optional blocks As Dictionary(Of Integer, Integer) = Nothing) As (Integer, String)() Return process(to_array(code), messages, blocks) End Function Public Function process(code As Byte(), messages As IEnumerable(Of String), Optional blocks As Dictionary(Of Integer, Integer) = Nothing) As (Integer, String)() Dim response As new List(Of (Integer, String))() Dim k As Integer = 0 Dim l = code.Length * power Dim i As Integer = 0 Dim m As Integer = messages.Count() If blocks Is Nothing Then blocks = New Dictionary(Of Integer, Integer)() While i < l If blocks.ContainsKey(i) AndAlso blocks(i) > 0 Then Dim logarithm As Integer = CInt(Math.Log(blocks(i), 2)) Dim _k As Integer If logarithm = 0 Then logarithm = 1 _k = to_integer(get_range(code, i, logarithm)) If _k > 0 Then _k = k + _k response.Add((_k, If(k < m, messages(k), ""))) End If k += blocks(i) i += logarithm Else If (code(i \ power) And (1 << i Mod power)) <> 0 Then response.Add((k, If(k < m, messages(k), ""))) End If k += 1 i += 1 End If End While return response.ToArray() End Function Public Function process(code As Integer, messages As IEnumerable(Of String), Optional blocks As Dictionary(Of Integer, Integer) = Nothing) As (Integer, String)() Return process(to_array(code), messages, blocks) End Function Public Function bitwise(code As String, bits As Integer) As String Return to_string(get_range(to_array(code), 0, bits)) End Function Public Function bitwise(code As Byte(), bits As Integer) As Byte() If code.Length = 0 OrElse bits = 0 Then Return code Dim shift As Byte = CByte(Math.Abs(bits) Mod power) Dim mask As Integer = _base - 1 Dim hexas As List(Of Byte) = code.ToList() If bits < 0 Then hexas.RemoveRange(0, -bits \ power) If shift <> 0 AndAlso hexas.Count() <> 0 Then Dim l As Integer = hexas.Count() - 2 For i As Integer = 0 To l hexas(i) = CByte(((hexas(i) >> shift) Or (hexas(i + 1) << (power - shift))) And mask) Next hexas(hexas.Count - 1) = CByte((hexas.Last() >> shift) And mask) End If Else If shift <> 0 Then Dim last_hexa As Byte = hexas.Last() << shift For i As Integer = hexas.Count() - 1 To 1 Step -1 hexas(i) = CByte(((hexas(i) << shift) Or (hexas(i - 1) >> (power - shift))) And mask) Next hexas(0) = CByte((hexas(0) << shift) And mask) If last_hexa >= _base Then hexas.Add(CByte(last_hexa >> power)) End If For i As Integer = bits \ power To 1 Step -1 hexas.Insert(0, 0) Next End If Return clean(hexas.ToArray()) End Function Public Function bitwise(code As Integer, bits As Integer) As Integer Return ( If(bits > 0, code << bits, If(bits < 0, code >> -bits, code))) End Function Public Function reset(code As String, [from] As Integer, Optional bits As Integer = 0, Optional reversed As Boolean = False) As String Return to_string(reset(to_array(code), [from], bits, reversed)) End Function Public Function reset(code As Byte(), [from] As Integer, Optional bits As Integer = 0, Optional reversed As Boolean = False) As Byte() Dim hexas As List(Of Byte) = code.ToList() Dim hexa_from As Integer Dim hexa_to As Integer Dim l As Integer Dim from_mask As Byte Dim to_mask As Byte get_from_bits(code, [from], bits) hexa_from = [from] \ power hexa_to = ([from] + bits) \ power If reversed Then l = [from] Mod power from_mask = CByte(((1 << power - l) - 1) << l) to_mask = Cbyte(((1 << ([from] + bits)) - 1) Mod power) For i As Integer = 0 To hexas.Count() - 1 If i < hexa_from AndAlso i > hexa_to Then hexas(i) = 0 Next If hexa_from = hexa_to Then hexas(hexa_to) = CByte(hexas(hexa_to) And (from_mask Or to_mask)) Else hexas(hexa_from) = CByte(hexas(hexa_from) And from_mask) If hexa_to < hexas.Count() Then hexas(hexa_to) = CByte(hexas(hexa_to) And to_mask) End If Else l = ([from] + bits) Mod power from_mask = CByte((1 << ([from] Mod power)) - 1) to_mask = CByte(((1 << (power - l)) - 1) << l) If hexa_from = hexa_to Then hexas(hexa_to) = CByte(hexas(hexa_to) And (from_mask Or to_mask)) Else hexas(hexa_from) = CByte(hexas(hexa_from) And from_mask) For i As Integer = hexa_from + 1 To hexa_to - 1 If i < hexas.Count() Then hexas(i) = 0 Next If hexa_to < hexas.Count() Then hexas(hexa_to) = CByte(hexas(hexa_to) And to_mask) End If End If Return clean(hexas.ToArray()) End Function Public Function reset(code As Integer, [from] As Integer, Optional bits As Integer = 0, Optional reversed As Boolean = False) As Integer get_from_bits(code, [from], bits) If [from] + bits > 31 Then bits = 31 - [from] Return code And ( If(reversed, ((1 << bits) - 1) << [from], ((1 << get_bits(code)) << [from] + bits Or ((1 << [from]) - 1)))) End Function Public Function has(code As String, [from] As Integer, bits As Integer) As Boolean Return get_range(to_array(code), [from], bits).Length > 0 End Function Public Function has(code As Byte(), [from] As Integer, bits As Integer) As Boolean Return get_range(code, [from], bits).Length > 0 End Function Public Function has(code As Integer, [from] As Integer, bits As Integer) As Boolean Return get_range(code, [from], bits) <> 0 End Function Public Function [set]([error] As String, code As String, Optional [from] As Integer = 0, Optional bits As Integer = 0) As String Return to_string([set](to_array([error]), to_array(code), [from], bits)) End Function Public Function [set]([error] As String, code As Byte(), Optional [from] As Integer = 0, Optional bits As Integer = 0) As String Return to_string([set](to_array([error]), code, [from], bits)) End Function Public Function [set]([error] As String, code As Integer, Optional [from] As Integer = 0, Optional bits As Integer = 0) As String Return to_string([set](to_array([error]), to_array(code), [from], bits)) End Function Public Function [set]([error] As Byte(), code As String, Optional [from] As Integer = 0, Optional bits As Integer = 0) As Byte() Return [set]([error], to_array(code), [from], bits) End Function Public Function [set]([error] As Byte(), code As Byte(), Optional [from] As Integer = 0, Optional bits As Integer = 0) As Byte() Dim l As Integer Dim m As Integer Dim n As Integer Dim results As New List(Of Byte)() If bits <> 0 Then [error] = reset([error], [from], bits) m = [error].Length End If If [from] <> 0 Then code = bitwise(code, [from]) n = code.Length End If l = If(m > n, m, n) For i As Integer = 0 To l - 1 results.Add(CByte( (If(i < m, [error](i), CByte(0))) Or (If(i < n, code(i), CByte(0))) )) Next Return clean(results.ToArray()) End Function Public Function [set]([error] As Byte(), code As Integer, Optional [from] As Integer = 0, Optional bits As Integer = 0) As Byte() Return [set]([error], to_array(code), [from], bits) End Function Public Function [set]([error] As Integer, code As String, Optional [from] As Integer = 0, Optional bits As Integer = 0) As Integer Return [set]([error], to_integer(code), [from], bits) End Function Public Function [set]([error] As Integer, code As Byte(), Optional [from] As Integer = 0, Optional bits As Integer = 0) As Integer Return [set]([error], to_integer(code), [from], bits) End Function Public Function [set]([error] As Integer, code As Integer, Optional [from] As Integer = 0, Optional bits As Integer = 0) As Integer If bits <> 0 Then [error] = reset([error], [from], bits) If [from] <> 0 Then [error] = bitwise([error], [from]) Return [error] Or code End Function Public Shared Function get_keys(items As Object) As String() Dim keys As New List(Of String)() If TypeOf items Is String Then If RE_KEY.IsMatch(DirectCast(items, String)) Then keys.Add(DirectCast(items, String)) ElseIf TypeOf items Is String() Then For Each item As String In DirectCast(items, String()) If RE_KEY.IsMatch(item) AndAlso Not keys.Contains(item) Then keys.Add(item) Next ElseIf TypeOf items Is IEnumerable(Of Object) Then For Each item As Object In DirectCast(items, IEnumerable(Of Object)) If item Is Nothing Then Continue For If TypeOf item Is String Then If RE_KEY.IsMatch(DirectCast(item, String)) AndAlso Not keys.Contains(DirectCast(item, String)) Then keys.Add(DirectCast(item, String)) Else For Each key As String In get_keys(item) If Not keys.Contains(key) Then keys.Add(key) Next End If Next End If Return keys.ToArray() End Function Public Shared Function get_dictionaries(items As Object) As List(Of Dictionary(Of String, Object)) Dim dictionaries As New List(Of Dictionary(Of String, Object))() If TypeOf items Is Dictionary(Of String, Object) Then dictionaries.Add(DirectCast(items, Dictionary(Of String, Object))) ElseIf TypeOf items Is IEnumerable(Of Object) Then For Each item As Object In DirectCast(items, IEnumerable(Of Object)) dictionaries.AddRange(get_dictionaries(item)) Next End If Return dictionaries End Function Public Shared Function [get](Of T)(keys As Object, inputs As Object, Optional _default As T = Nothing) As T Dim keys_list As String() = get_keys(keys) If keys_list.Length <> 0 Then For Each dictionary As Dictionary(Of String, Object) In get_dictionaries(inputs) For Each key As String In keys_list Dim value As Object = Nothing If dictionary.TryGetValue(key, value) AndAlso TypeOf value Is T Then Return DirectCast(value, T) Next Next End If Return _default End Function Public Shared Function Unique(Of T)(items As IEnumerable(Of T)) As T() Return items.Distinct().ToArray() End Function Public Shared Function is_array(value As Object) As Boolean Return TypeOf value Is Array End Function Public Shared Function is_integer(value As Object) As Boolean Return TypeOf value Is Integer End Function Public Shared Sub for_each_enumerate(Of T)(items As IEnumerable(Of T), action As Action(Of T, Integer)) Dim index As Integer = 0 For Each item As T In items action(item, index) index += 1 Next End Sub End Class End Namespace