diff --git a/.gitignore b/.gitignore index 237a112..764ccae 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ __pycache__ /VB/obj /VB/bin /Data -/Public/data \ No newline at end of file +/Public/data +/KyMAN_ErrorsManager.egg-info \ No newline at end of file diff --git a/CSharp/ErrorsManager.cs b/CSharp/ErrorsManager.cs index 924708e..9455cae 100644 --- a/CSharp/ErrorsManager.cs +++ b/CSharp/ErrorsManager.cs @@ -298,13 +298,13 @@ namespace ErrorsManager{ if(from > 0) code = (code >> from) & ((1 << (31 - from)) - 1); - if(bits <= 0 || bits >= 31) - return code; + if(bits <= 0 || from >= 31) + return 0; if(from + bits > 31) bits = 31 - from; - return code & ((1 << bits) - 1); + return (code >> from) & ((1 << bits) - 1); } public (int, string)[] process(string code, IEnumerable messages){ @@ -352,7 +352,7 @@ namespace ErrorsManager{ } public byte[] bitwise(byte[] code, int bits){ if(code.Length == 0 || bits == 0) - return code; + return clean(code); byte shift = (byte)(Math.Abs(bits) % power); int mask = _base - 1; diff --git a/Python/ErrorsManager.py b/Python/ErrorsManager.py index 1f776fc..9b4338a 100644 --- a/Python/ErrorsManager.py +++ b/Python/ErrorsManager.py @@ -1,2 +1,501 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- \ No newline at end of file +# -*- coding: utf-8 -*- + +from math import log2, ceil +import string +from typing import Any, Optional, Sequence, Self +from re import compile as re_compile, Pattern as REPattern, IGNORECASE as RE_IGNORECASE + +class ErrorsManager: + + ALPHABET:tuple[str] = tuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=") + + ERRORS_MESSAGES:tuple[str] = ( + "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" + ) + + RE_KEY:REPattern = re_compile(r"^[a-z_][a-z0-9_]*$", RE_IGNORECASE) + + def __init__(self:Self, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None: + + self.__error:int = 0 + self.__alphabet:tuple[str] = tuple() + self.__dictionary:dict[str, int] = {} + self.__base:int = 0 + self.__power:int = 0 + + self.set_alphabet( + self.get("alphabet", inputs, self.ALPHABET), + self.get("base", inputs, 64) + ) + + def set_alphabet(self:Self, alphabet:Optional[str|Sequence[str]] = None, base:int = 64) -> int: + + original_length:int + i:int + character:str + + self.__error = 0 + + if alphabet is None: + self.__alphabet = self.ALPHABET + elif self.is_string(alphabet) or self.is_array(alphabet): + self.__alphabet = tuple(alphabet) + else: + self.__error |= 1 << 2 + self.__alphabet = self.ALPHABET + + original_length = len(self.__alphabet) + + self.__alphabet = tuple(self.unique(self.__alphabet)) + + if len(self.__alphabet) < 2: + self.__error |= 1 << 3 + self.__alphabet = self.ALPHABET + if len(self.__alphabet) != original_length: + self.__error |= 1 << 4 + if len(self.__alphabet) > 128: + self.__error |= 1 << 5 + + self.__error |= ( + 1 << 0 if base < 2 else + 1 << 1 if base > 128 else + 1 << 2 if base >= len(self.__alphabet) else + 0) << 6 + + if not self.__error >> 6: + self.__alphabet = self.__alphabet[0:base] + + self.__power = int(log2(len(self.__alphabet[0:128]))) + self.__base = 2 ** self.__power + self.__alphabet = self.__alphabet[0:self.__base] + + for i, character in enumerate(self.__alphabet): + self.__dictionary[character] = i + + return self.__error + + def get_alphabet(self:Self) -> str: + return "".join(self.__alphabet) + + def to_array(self:Self, code:str|Sequence[int]|int) -> list[int]: + if self.is_string(code): + return [self.__dictionary[character] for character in code] + if self.is_array(code): + return list(code) + if self.is_integer(code): + + hexas:list[int] = [] + + while code: + hexas.append(code % self.__base) + code //= self.__base + + return hexas or [0] + return [] + + def to_string(self:Self, code:list[int]|str|Sequence[int]|int) -> str: + if self.is_string(code): + return code + if self.is_array(code): + return "".join(self.__alphabet[i] for i in code) + if self.is_integer(code): + + hexas:str = "" + + while code: + hexas += self.__alphabet[code % self.__base] + code //= self.__base + + return hexas or self.__alphabet[0] + return "" + + def to_integer(self:Self, code:str|Sequence[int]|int) -> int: + if self.is_string(code): + return sum(self.__dictionary[character] * (self.__base ** i) for i, character in enumerate(code)) + if self.is_array(code): + return sum(i * (self.__base ** j) for j, i in enumerate(code)) + if self.is_integer(code): + return code + return 0 + + def to_string_binary(self:Self, code:str|Sequence[int]|int) -> str: + if self.is_string(code): + return "".join(("0000000" + "{0:b}".format(self.__dictionary[character]))[-self.__power:] for character in code[::-1]) + if self.is_array(code): + return "".join(("0000000" + "{0:b}".format(hexa))[-self.__power:] for hexa in code[::-1]) + if self.is_integer(code): + + binary:str = "{0:b}".format(code) + module:int = len(binary) % self.__power + + return ("0000000"[:self.__power - module] if module else "") + binary + return "" + + def get_bits(self:Self, code:str|Sequence[int]|int) -> int: + if self.is_string(code): + return (len(code) - 1) * self.__power + ceil(log2(self.__dictionary[code[-1]] + 1)) + if self.is_array(code): + return (len(code) - 1) * self.__power + ceil(log2(code[-1] + 1)) + if self.is_integer(code): + return code.bit_length() + return 0 + + def get_from_bits(self:Self, code:str|Sequence[int]|int, _from:int, bits:int) -> tuple[int, int]: + + if _from < 0: + _from = self.get_bits(code) + _from + if _from < 0: + _from = 0 + if bits < 0: + _from += bits + bits = -bits + if _from < 0: + bits += _from + _from = 0 + + return _from, bits + + def clean(self:Self, code:str|Sequence[int]|int) -> str|Sequence[int]|int|None: + if self.is_string(code): + + l:int = len(code) + + while l > 0 and code[l - 1] != self.__alphabet[0]: + l -= 1 + + return code[:l] or self.__alphabet[0] + if self.is_array(code): + + l:int = len(code) + + while l > 0 and code[l - 1] == 0: + l -= 1 + + return code[:l] or [0] + if self.is_integer(code): + return code + return None + + def get_range(self:Self, code:str|Sequence[int]|int, _from:int, bits:int) -> str|Sequence[int]|int|None: + if self.is_string(code): + return self.to_string(self.get_range(self.to_array(code), _from, bits)) + if self.is_array(code): + + hexas:list[int] + + _from, bits = self.get_from_bits(code, _from, bits) + + if not bits: + bits = self.get_bits(code) - _from + if bits <= 0: + return [0] + + hexas = list(code) + + if _from > 0: + + shift:int = _from % self.__power + mask:int = (self.__base) - 1 + + hexas = hexas[_from // self.__power:] + if shift and len(hexas): + + hexa:int + i:int + + for i, hexa in enumerate(hexas[:-1]): + hexas[i] = ((hexa >> shift) | (hexas[i + 1] << self.__power - shift)) & mask + hexas[-1] >>= shift + + if bits > 0: + + shift:int = bits % self.__power + + hexas = hexas[0:int(ceil(bits / self.__power))] + if shift and len(hexas): + hexas[len(hexas) - 1] &= (1 << shift) - 1 + + return self.clean(hexas) + if self.is_integer(code): + + _from, bits = self.get_from_bits(code, _from, bits) + + if not bits: + bits = self.get_bits(code) - _from + if bits <= 0 or _from >= 31: + return 0 + + if _from + bits > 31: + bits = 31 - _from + + return (code >> _from) & ((1 << bits) - 1) + return None + + def process(self:Self, code:str|Sequence[int]|int, messages:Sequence[str], blocks:dict[int, int]) -> list[tuple[int, str]]: + if self.is_string(code) or self.is_integer(code): + return self.process(self.to_array(code), messages, blocks) + if self.is_array(code): + + response:list[tuple[int, str]] = [] + k:int = 0 + i:int + l:int = len(messages) + i:int = 0 + m:int = len(code) * self.__power + + if blocks is None: + blocks = {} + + while i < m: + if i in blocks and blocks[i]: + + logarithm:int = int(ceil(log2(blocks[i]))) + _k:int = self.to_integer(self.get_range(code, i, logarithm if logarithm else (logarithm := 0))) + + if _k: + _k += k + response.append((_k, messages[k] if k < l else "error_message_" + str(_k))) + + k += blocks[i] + i += logarithm + + else: + if code[i // self.__power] & (1 << (i % self.__power)): + response.append((k, messages[k] if k < l else "error_message_" + str(k))) + k += 1 + i += 1 + + return response + return [] + + def bitwise(self:Self, code:str|Sequence[int]|int, bits:int) -> str|Sequence[int]|int|None: + if self.is_string(code): + return self.to_string(self.bitwise(self.to_array(code), bits)) + if self.is_array(code): + if not len(code) or not bits: + return self.clean(code) + + shift:int = abs(bits) % self.__power + mask:int = self.__base - 1 + hexas:list[int] = list(code) + + if bits < 0: + + hexas = hexas[-bits // self.__power:] + + if shift and len(hexas): + + hexa:int + i:int + + for i, hexa in enumerate(hexas[:-1]): + hexas[i] = ((hexa >> shift) | (hexas[i + 1] << self.__power - shift)) & mask + hexas[-1] >>= shift + + else: + + if shift: + + last_hexa:int = hexas[-1] << shift + + for i, hexa in reversed(list(enumerate(hexas))[1:]): + hexas[i] = ((hexas[i] << shift) | (hexas[i - 1] >> self.__power - shift)) & mask + hexas[0] = (hexas[0] << shift) & mask + + if last_hexa >= self.__base: + hexas.append(last_hexa >> self.__power) + + hexas = [0] * (bits // self.__power) + hexas + + return self.clean(hexas) + if self.is_integer(code): + return ( + code << bits if bits > 0 else + code >> -bits if bits < 0 else + code) + return None + + def reset(self:Self, code:str|Sequence[int]|int, _from:int, bits:int = 0, reversed:bool = False) -> str|Sequence[int]|int|None: + if self.is_string(code): + return self.to_string(self.reset(self.to_array(code), _from, bits, reversed)) + if self.is_array(code): + + hexas:list[int] = list(code) + hexa_from:int + hexa_to:int + l:int + from_mask:int + to_mask:int + + _from, bits = self.get_from_bits(code, _from, bits) + hexa_from = _from // self.__power + hexa_to = (_from + bits) // self.__power + + if reversed: + + i:int + + l = _from % self.__power + from_mask = ~((1 << l) - 1) + to_mask = (1 << ((_from + bits) % self.__power)) - 1 + + for i in range(len(hexas)): + if i < hexa_from or i > hexa_to: + hexas[i] = 0 + + if hexa_from == hexa_to: + hexas[hexa_from] &= from_mask & to_mask + else: + hexas[hexa_from] &= from_mask + if hexa_to < len(hexas): + hexas[hexa_to] &= to_mask + + elif hexa_from < len(hexas): + + l = (_from + bits) % self.__power + from_mask = ((1 << (_from % self.__power)) - 1) + to_mask = ((1 << (self.__power - l)) - 1) << l + + if hexa_from == hexa_to: + hexas[hexa_from] &= from_mask | to_mask + else: + + i:int + m:int = len(hexas) + + hexas[hexa_from] &= from_mask + for i in range(hexa_from + 1, hexa_to): + if i >= m: + break + hexas[i] = 0 + if hexa_to < m: + hexas[hexa_to] &= to_mask + + return self.clean(hexas) + if self.is_integer(code): + + _from, bits = self.get_from_bits(code, _from, bits) + if _from + bits > 31: + bits = 31 - _from + + return code & ( + ((1 << bits) - 1) << _from if reversed else + ((1 << self.get_bits(code)) - 1 << _from + bits) | ((1 << _from) - 1)) + return None + + def has(self:Self, code:str|Sequence[int]|int, _from:int = 0, bits:int = 0) -> bool: + if self.is_string(code): + for hexa in self.get_range(code, _from, bits): + if self.__dictionary[hexa]: + return True + if self.is_array(code): + for hexa in self.get_range(code, _from, bits): + if hexa: + return True + if self.is_integer(code) and self.get_range(code, _from, bits): + return True + return False + + def set(self:Self, code:str|Sequence[int]|int, error:str|Sequence[int]|int, _from:int, bits:int = 0) -> str|Sequence[int]|int|None: + if self.is_string(code): + return self.to_string(self.set(self.to_array(code), error, _from, bits)) + if self.is_array(code): + + l:int + n:int = len(error := self.to_array(error)) + m:int = len(code) + results:list[int] = [] + + if bits: + m = len(code := self.reset(code, _from, bits)) + if _from: + n = len(error := self.bitwise(error, _from)) + l = m if m > n else n + + for i in range(l): + results.append( + (error[i] if i < n else 0) | + (code[i] if i < m else 0) + ) + + return self.clean(results) + if self.is_integer(code): + + error = self.to_integer(error) + if bits: + code = self.reset(code, _from, bits) + if _from: + error = self.bitwise(error, _from) + + return error | code + return None + + @classmethod + def get_keys(cls:type[Self], *items:list[Any|None]) -> list[str]: + + keys:list[str] = [] + + for item in items: + if isinstance(item, str): + cls.RE_KEY.match(item) and item not in keys and keys.append(item) + elif isinstance(item, (list, tuple)): + + key:str + + for key in cls.get_keys(*item): + key not in keys and keys.append(key) + + return keys + + @classmethod + def get_dictionaries(cls:type[Self], *items:list[Any|None]) -> list[dict[str, Any|None]]: + + dictionaries:list[dict[str, Any|None]] = [] + + for item in items: + if isinstance(item, dict): + dictionaries.append(item) + elif isinstance(item, (list, tuple)): + dictionaries.extend(cls.get_dictionaries(*item)) + + return dictionaries + + @classmethod + def get(cls:type[Self], keys:str|list[str], inputs:dict[str, Any|None]|Sequence[Any|None], default:Optional[Any] = None) -> Any|None: + if len(keys := cls.get_keys(keys)): + + subinputs:dict[str, Any|None] + + for subinputs in cls.get_dictionaries(inputs): + + key:str + + for key in keys: + if key in subinputs: + return subinputs[key] + return default + + @staticmethod + def unique(items:str|bytes|Sequence[Any|None]) -> list[Any|None]: + return [item for i, item in enumerate(items) if list(items).index(item) == i] + + @staticmethod + def is_string(item:Any|None) -> bool: + return isinstance(item, str) + + @staticmethod + def is_array(item:Any|None) -> bool: + return isinstance(item, (list, tuple)) + + @staticmethod + def is_integer(item:Any|None) -> bool: + return isinstance(item, int) \ No newline at end of file diff --git a/Python/Tests.py b/Python/Tests.py new file mode 100644 index 0000000..1e5753a --- /dev/null +++ b/Python/Tests.py @@ -0,0 +1,289 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from random import randint +from typing import Sequence, Self +from ErrorsManager import ErrorsManager + +class FullError: + + def __init__(self:Self, errors:ErrorsManager, value:int|str|Sequence[int]) -> None: + + self.integer:int = 0 + self.string:str = "" + self.array:list[int] = [] + + if ErrorsManager.is_integer(value): + self.integer = value + self.string = errors.to_string(value) + self.array = errors.to_array(value) + elif ErrorsManager.isstring(value): + self.integer = errors.to_integer(value) + self.string = value + self.array = errors.to_array(value) + elif ErrorsManager.is_array(value): + self.integer = errors.to_integer(value) + self.string = errors.to_string(value) + self.array = list(value) + + @staticmethod + def print(array:Sequence[int]) -> str: + return "[" + ", ".join(str(i) for i in array) + "]" + +class Tests: + + @staticmethod + def errors(): + + errors:ErrorsManager = ErrorsManager() + error:FullError = FullError(errors, 217934237) + reset:FullError = FullError(errors, 0) + + reset.integer = errors.reset(error.integer, -5, 12) + reset.string = errors.reset(error.string, -5, 12) + reset.array = errors.reset(error.array, -5, 12) + + print(f"RESET: from {-5} bits {12}") + print(f"INTEGER: {errors.to_string_binary(error.integer)} - {errors.to_string_binary(reset.integer)}") + print(f"STRING: {errors.to_string_binary(error.string)} - {errors.to_string_binary(reset.string)}") + print(f"ARRAY: {errors.to_string_binary(error.array)} - {errors.to_string_binary(reset.array)}") + print() + + @staticmethod + def conversions(tests: int = 10, inputs: dict = None): + + errors:ErrorsManager = ErrorsManager(inputs) + + for _ in range(tests): + + error:FullError = FullError(errors, randint(0, 1 << 16)) + + print(f"INTEGER: {errors.to_integer(error.integer)}, {errors.to_integer(error.string)}, {errors.to_integer(error.array)}") + print(f"STRING: {errors.to_string(error.integer)}, {errors.to_string(error.string)}, {errors.to_string(error.array)}") + print(f"ARRAY: {FullError.print(errors.to_array(error.integer))}, {FullError.print(errors.to_array(error.string))}, {FullError.print(errors.to_array(error.array))}") + print() + + return errors + + @staticmethod + def binaries(tests: int = 10, inputs: dict = None): + + errors:ErrorsManager = ErrorsManager(inputs) + + for _ in range(tests): + + error:FullError = FullError(errors, randint(0, 1 << 16)) + integer:str = errors.to_string_binary(error.integer) + string:str = errors.to_string_binary(error.string) + array:str = errors.to_string_binary(error.array) + + print("OK: " + ("YES" if integer == string == array else "NO")) + print(f"INTEGER: {integer}") + print(f"STRING: {string}") + print(f"ARRAY: {array}") + print() + + return errors + + @staticmethod + def alphabet(tests: int = 10): + for _ in range(tests): + + errors:ErrorsManager = Tests.conversions(1, {"base": randint(2, 128)}) + + print(f"^^^ ALPHABET: {', '.join(errors.get_alphabet())} ^^^") + print() + + @staticmethod + def bitwise(tests: int = 10): + + errors:ErrorsManager = ErrorsManager() + + for _ in range(tests): + + error:FullError = FullError(errors, randint(0, 1 << randint(0, 16))) + shifted:FullError = FullError(errors, 0) + unshifted:FullError = FullError(errors, 0) + bitwise:int = randint(-10, 10) + + print(f"BITWISE: {bitwise}") + + shifted.integer = errors.bitwise(error.integer, bitwise) + shifted.string = errors.bitwise(error.string, bitwise) + shifted.array = errors.bitwise(error.array, bitwise) + unshifted.integer = errors.bitwise(shifted.integer, -bitwise) + unshifted.string = errors.bitwise(shifted.string, -bitwise) + unshifted.array = errors.bitwise(shifted.array, -bitwise) + + print(f"INTEGER: {errors.to_string_binary(error.integer)} - {error.integer}") + print(f"STRING: {errors.to_string_binary(error.string)} - {error.string}") + print(f"ARRAY: {errors.to_string_binary(error.array)} - {FullError.print(error.array)}") + print(f"INTEGER: {errors.to_string_binary(shifted.integer)} - {shifted.integer}") + print(f"STRING: {errors.to_string_binary(shifted.string)} - {shifted.string}") + print(f"ARRAY: {errors.to_string_binary(shifted.array)} - {FullError.print(shifted.array)}") + print(f"INTEGER: {errors.to_string_binary(unshifted.integer)} - {unshifted.integer}") + print(f"STRING: {errors.to_string_binary(unshifted.string)} - {unshifted.string}") + print(f"ARRAY: {errors.to_string_binary(unshifted.array)} - {FullError.print(unshifted.array)}") + print() + + @staticmethod + def bitwise_sucesive(tests: int = 10): + + errors = ErrorsManager() + error = FullError(errors, randint(0, 1 << 16)) + i:int + + print(f"INTEGER: {errors.to_string_binary(error.integer)} - {error.integer}") + print(f"STRING: {errors.to_string_binary(error.string)} - {error.string}") + print(f"ARRAY: {errors.to_string_binary(error.array)} - {FullError.print(error.array)}") + print() + + for i in range(-tests, tests): + + shifted:FullError = FullError(errors, 0) + + print(f"BITWISE: {i}") + + shifted.integer = errors.bitwise(error.integer, i) + shifted.string = errors.bitwise(error.string, i) + shifted.array = errors.bitwise(error.array, i) + + + print(f"INTEGER: {errors.to_string_binary(shifted.integer)} - {shifted.integer}") + print(f"STRING: {errors.to_string_binary(shifted.string)} - {shifted.string}") + print(f"ARRAY: {errors.to_string_binary(shifted.array)} - {FullError.print(shifted.array)}") + print() + + @staticmethod + def bits(tests: int = 10): + + errors:ErrorsManager = ErrorsManager() + + for _ in range(tests): + + error:FullError = FullError(errors, randint(0, 1 << randint(0, 28))) + from_value:int = randint(-15, 15) + bits_value:int = randint(-13, 13) + from_values:list[int] = [from_value, from_value, from_value] + bits_values:list[int] = [bits_value, bits_value, bits_value] + + from_values[0], bits_values[0] = errors.get_from_bits(error.integer, from_values[0], bits_values[0]) + from_values[1], bits_values[1] = errors.get_from_bits(error.string, from_values[1], bits_values[1]) + from_values[2], bits_values[2] = errors.get_from_bits(error.array, from_values[2], bits_values[2]) + + + print(f"CODE: {error.integer} - {error.string} - {FullError.print(error.array)}") + print(f"ERROR: {errors.to_string_binary(error.integer)} - {errors.get_bits(error.integer)} - {errors.get_bits(error.string)} - {errors.get_bits(error.array)}") + print(f"FROM: {from_value} - {from_values[0]}, {from_values[1]}, {from_values[2]}") + print(f"BITS: {bits_value} - {bits_values[0]}, {bits_values[1]}, {bits_values[2]}") + print() + + @staticmethod + def reset(tests: int = 10): + + errors:ErrorsManager = ErrorsManager() + + for _ in range(tests): + + error:FullError = FullError(errors, randint(0, 1 << 28)) + from_value:int = randint(-15, 15) + bits_value:int = randint(-13, 13) + reversed:bool = randint(0, 1) == 0 + reset:FullError = FullError(errors, 0) + + reset.integer = errors.reset(error.integer, from_value, bits_value, reversed) + reset.string = errors.reset(error.string, from_value, bits_value, reversed) + reset.array = errors.reset(error.array, from_value, bits_value, reversed) + + print(f"RESET: from {from_value} bits {bits_value} reversed {reversed}") + print(f"INTEGER: {errors.to_string_binary(error.integer)} - {errors.to_string_binary(reset.integer)}") + print(f"STRING: {errors.to_string_binary(error.string)} - {errors.to_string_binary(reset.string)}") + print(f"ARRAY: {errors.to_string_binary(error.array)} - {errors.to_string_binary(reset.array)}") + print() + + @staticmethod + def ranges(tests: int = 10): + + errors:ErrorsManager = ErrorsManager() + + for _ in range(tests): + + error:FullError = FullError(errors, randint(0, 1 << 28)) + from_value:int = randint(-15, 15) + bits_value:int = randint(-13, 13) + range_error:FullError = FullError(errors, 0) + + print(f"RANGE: from {from_value} bits {bits_value}") + errors.get_from_bits(error.string, from_value, bits_value) + print(f"REAL: from {from_value} bits {bits_value}") + + range_error.integer = errors.get_range(error.integer, from_value, bits_value) + range_error.string = errors.get_range(error.string, from_value, bits_value) + range_error.array = errors.get_range(error.array, from_value, bits_value) + + print(f"INTEGER: {errors.to_string_binary(error.integer)} - {errors.to_string_binary(range_error.integer)}") + print(f"STRING: {errors.to_string_binary(error.string)} - {errors.to_string_binary(range_error.string)}") + print(f"ARRAY: {errors.to_string_binary(error.array)} - {errors.to_string_binary(range_error.array)}") + print() + + @staticmethod + def has(tests: int = 10): + + errors:ErrorsManager = ErrorsManager() + + for _ in range(tests): + + error:FullError = FullError(errors, randint(0, 1 << 28)) + from_value:int = randint(-15, 15) + bits_value:int = randint(-13, 13) + + print(f"HAS: from {from_value} bits {bits_value}") + print(f"INTEGER: {errors.has(error.integer, from_value, bits_value)} - {errors.to_string_binary(error.integer)} - {errors.to_string_binary(errors.get_range(error.integer, from_value, bits_value))}") + print(f"STRING: {errors.has(error.string, from_value, bits_value)} - {errors.to_string_binary(error.string)} - {errors.to_string_binary(errors.get_range(error.string, from_value, bits_value))}") + print(f"ARRAY: {errors.has(error.array, from_value, bits_value)} - {errors.to_string_binary(error.array)} - {errors.to_string_binary(errors.get_range(error.array, from_value, bits_value))}") + print() + + @staticmethod + def set(tests: int = 10): + + errors:ErrorsManager = ErrorsManager() + + for _ in range(tests): + + error:FullError = FullError(errors, randint(0, 1 << 15)) + value:FullError = FullError(errors, randint(0, 1 << 15)) + from_value:int = randint(-15, 15) + bits_value:int = randint(-13, 13) + set_integer:FullError = FullError(errors, 0) + set_string:FullError = FullError(errors, 0) + set_array:FullError = FullError(errors, 0) + + set_integer.integer = errors.set(error.integer, value.integer, from_value, bits_value) + set_string.integer = errors.set(error.integer, value.string, from_value, bits_value) + set_array.integer = errors.set(error.integer, value.array, from_value, bits_value) + set_integer.string = errors.set(error.string, value.integer, from_value, bits_value) + set_string.string = errors.set(error.string, value.string, from_value, bits_value) + set_array.string = errors.set(error.string, value.array, from_value, bits_value) + set_integer.array = errors.set(error.array, value.integer, from_value, bits_value) + set_string.array = errors.set(error.array, value.string, from_value, bits_value) + set_array.array = errors.set(error.array, value.array, from_value, bits_value) + + print(f"SET: from {from_value} bits {bits_value} to [{value.string}, {FullError.print(value.array)}, {value.integer}]") + print(f"ERROR: {errors.to_string_binary(error.integer)} - VALUE: {errors.to_string_binary(value.integer)}") + print(f"INTEGER: {errors.to_string_binary(set_integer.integer)} - {errors.to_string_binary(set_integer.string)} - {errors.to_string_binary(set_integer.array)}") + print(f"STRING: {errors.to_string_binary(set_string.integer)} - {errors.to_string_binary(set_string.string)} - {errors.to_string_binary(set_string.array)}") + print(f"ARRAY: {errors.to_string_binary(set_array.integer)} - {errors.to_string_binary(set_array.string)} - {errors.to_string_binary(set_array.array)}") + print() + + +# Tests.errors() +# Tests.conversions() +# Tests.binaries() +# Tests.alphabet() +# Tests.bitwise() +# Tests.bitwise_sucesive() +# Tests.bits() +# Tests.reset() +# Tests.ranges() +# Tests.has() +Tests.set() \ No newline at end of file diff --git a/README.md b/README.md index 362fe1f..ecc501f 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,25 @@ Y luego ejecutar: dotnet build ErrorsManager.csproj -c Release ``` +# Python + +Implementación del proyecto sobre el usuario local mediante enlace simbólico. + +```sh +#!/bin/bash +ln -s /ABSOLUTE/PATH/Python ~/.local/lib/python3.12/site-packages/ErrorsManager +``` + +Y para importarlo: + +```py +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from ErrorsManager.ErrorsManager import ErrorsManager + +``` + # Objetivos Leyenda: @@ -164,22 +183,22 @@ Tabla de objetivos: | Objetivo | Py | PHP | JS | MSL | MyS | CS | VB | Go | RS | C | CPP | |-------------------|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----| -| Common base | [X] | [ ] | [X] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| set_alphabet | [X] | [ ] | [X] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| get_alphabet | [ ] | [ ] | [ ] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| to_array | [X] | [ ] | [X] | | | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| to_integer | [X] | [ ] | [X] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| to_string | [X] | [ ] | [X] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| to_string_binary | [X] | [ ] | [X] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| process | [X] | [ ] | [X] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| get_bits | [ ] | [ ] | [ ] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| bitwise | [X] | [ ] | [X] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| get_from_bits | [ ] | [ ] | [ ] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| reset | [X] | [ ] | [X] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| get_range | [ ] | [ ] | [ ] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| has | [X] | [ ] | [X] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| clean | [ ] | [ ] | [ ] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | -| set | [X] | [ ] | [X] | [ ] | [ ] | [X] | [ ] | [ ] | [ ] | [ ] | [ ] | +| Common base | [X] | [ ] | [ ] | [-] | [ ] | [X] | [X] | [ ] | [ ] | [ ] | [ ] | +| set_alphabet | [X] | [ ] | [ ] | [-] | [ ] | [X] | [X] | [ ] | [ ] | [ ] | [ ] | +| get_alphabet | [X] | [ ] | [ ] | [-] | [ ] | [X] | [X] | [ ] | [ ] | [ ] | [ ] | +| to_array | [X] | [ ] | [ ] | | | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| to_integer | [X] | [ ] | [ ] | [-] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| to_string | [X] | [ ] | [ ] | [-] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| to_string_binary | [X] | [ ] | [ ] | [ ] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| process | [X] | [ ] | [ ] | [ ] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| get_bits | [X] | [ ] | [ ] | [-] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| bitwise | [X] | [ ] | [ ] | [-] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| get_from_bits | [X] | [ ] | [ ] | [-] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| reset | [X] | [ ] | [ ] | [-] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| get_range | [X] | [ ] | [ ] | [ ] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| has | [X] | [ ] | [ ] | [ ] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| clean | [X] | [ ] | [ ] | [ ] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | +| set | [X] | [ ] | [ ] | [ ] | [ ] | [-] | [-] | [ ] | [ ] | [ ] | [ ] | > **NOTA**: Los Checkbox indican el estado siendo los siguientes: diff --git a/SQLServer/ErrorsManager.server.sql b/SQLServer/ErrorsManager.server.sql index 4e36d4c..ff2f6d7 100644 --- a/SQLServer/ErrorsManager.server.sql +++ b/SQLServer/ErrorsManager.server.sql @@ -611,9 +611,9 @@ create procedure dbo.get_range( execute dbo.get_from_bits null, @integer, @from output, @bits output if @from > 0 set @code = dbo.shift(@code, @from) & (dbo.shift(1, 31 - @from) - 1) - if @bits > 0 || @bits < 31 begin + if @bits > 0 || @from < 31 begin if @from + @bits > 31 set @bits = 31 - @from - set @integer = @integer & (dbo.shift(1, @bits) - 1) + set @integer = dbo.shift(@integer, -@from) & (dbo.shift(1, @bits) - 1) end end diff --git a/VB/ErrorsManager.vb b/VB/ErrorsManager.vb index 5e7c425..930c106 100644 --- a/VB/ErrorsManager.vb +++ b/VB/ErrorsManager.vb @@ -290,10 +290,10 @@ Namespace ErrorsManager 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 bits <= 0 OrElse [from] >= 31 Then Return 0 If [from] + bits > 31 Then bits = 31 - [from] - Return code And ((1 << bits) - 1) + Return (code >> [from]) 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)() @@ -348,7 +348,7 @@ Namespace ErrorsManager End Function Public Function bitwise(code As Byte(), bits As Integer) As Byte() - If code.Length = 0 OrElse bits = 0 Then Return code + If code.Length = 0 OrElse bits = 0 Then Return clean(code) Dim shift As Byte = CByte(Math.Abs(bits) Mod power) Dim mask As Integer = _base - 1 diff --git a/version b/version index 28af839..a53741c 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.2.5 \ No newline at end of file +0.2.6 \ No newline at end of file