From e7d8e3826c60783744ed0b9d6b32f8a58d7fb746 Mon Sep 17 00:00:00 2001 From: KyMAN <0kyman0@gmail.com> Date: Mon, 27 Apr 2026 07:05:38 +0200 Subject: [PATCH] #wip: Building js, py, sql server and vb. --- .gitignore | 4 +- CSharp/ErrorsManager.cs | 11 +- CSharp/Tests.cs | 4 +- Public/ecma/ErrorsManager.ecma.js | 989 +++++++++++++++++----------- Public/ecma/Tests.ecma.js | 434 ++++++++++++ Public/test.html | 77 --- Public/tests.html | 28 + Python/Application/ErrorsManager.py | 15 - Python/ErrorsManager.py | 398 +---------- Python/tests.py | 65 -- Python/v2/ErrorsManager.py | 254 ------- Python/v2/tests.py | 48 -- SQLServer/ErrorsManager.server.sql | 621 +++++++++++++++++ VB/ErrorsManager.vb | 7 +- VB/Tests.vb | 4 +- version | 2 +- 16 files changed, 1716 insertions(+), 1245 deletions(-) create mode 100644 Public/ecma/Tests.ecma.js delete mode 100644 Public/test.html create mode 100644 Public/tests.html delete mode 100644 Python/Application/ErrorsManager.py delete mode 100644 Python/tests.py delete mode 100644 Python/v2/ErrorsManager.py delete mode 100644 Python/v2/tests.py create mode 100644 SQLServer/ErrorsManager.server.sql diff --git a/.gitignore b/.gitignore index b6dfe13..237a112 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ __pycache__ /CSharp/obj /CSharp/bin /VB/obj -/VB/bin \ No newline at end of file +/VB/bin +/Data +/Public/data \ No newline at end of file diff --git a/CSharp/ErrorsManager.cs b/CSharp/ErrorsManager.cs index bf6aab0..924708e 100644 --- a/CSharp/ErrorsManager.cs +++ b/CSharp/ErrorsManager.cs @@ -379,7 +379,7 @@ namespace ErrorsManager{ 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[i] = (byte)(((hexas[i] << shift) | (hexas[i - 1] >> (power - shift))) & mask); hexas[0] = (byte)((hexas[0] << shift) & mask); if(last_hexa >= _base) @@ -430,7 +430,7 @@ namespace ErrorsManager{ hexas[i] = 0; if(hexa_from == hexa_to) - hexas[hexa_to] &= (byte)(from_mask & to_mask); + hexas[hexa_to] &= (byte)(from_mask | to_mask); else{ hexas[hexa_from] &= from_mask; if(hexa_to < hexas.Count) @@ -452,6 +452,7 @@ namespace ErrorsManager{ if(hexa_to < hexas.Count) hexas[hexa_to] &= to_mask; } + } return clean(hexas.ToArray()); @@ -463,8 +464,8 @@ namespace ErrorsManager{ if(from + bits > 31) bits = 31 - from; - return code & (reversed ? - ~-(1 << bits) << from : + return code & ( + reversed ? ~-(1 << bits) << from : (~-(1 << get_bits(code)) << from + bits) | ~-(1 << from)); } @@ -537,10 +538,12 @@ namespace ErrorsManager{ } 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; } diff --git a/CSharp/Tests.cs b/CSharp/Tests.cs index 27af90e..920900f 100644 --- a/CSharp/Tests.cs +++ b/CSharp/Tests.cs @@ -97,7 +97,7 @@ namespace ErrorsManager{ FullError error = new FullError(errors, seed.Next(0, 1 << seed.Next(0, 16))); FullError shifted = new FullError(errors, 0); FullError unshifted = new FullError(errors, 0); - int bitwise = 10 - seed.Next(0, 20); + int bitwise = seed.Next(-10, 10); Console.WriteLine($"BITWISE: {bitwise}"); @@ -282,7 +282,7 @@ namespace ErrorsManager{ set_string.array = errors.set(error.array, value._string, from, bits); set_array.array = errors.set(error.array, value.array, from, bits); - Console.WriteLine($"SET: from {from} bits {bits} to {value}"); + Console.WriteLine($"SET: from {from} bits {bits} to [{value._string}, {FullError.print(value.array)}, {value.integer}]"); Console.WriteLine($"ERROR: {errors.to_string_binary(error.integer)} - VALUE: {errors.to_string_binary(value.integer)}"); Console.WriteLine($"INTEGER: {errors.to_string_binary(set_integer.integer)} - {errors.to_string_binary(set_integer._string)} - {errors.to_string_binary(set_integer.array)}"); Console.WriteLine($"STRING: {errors.to_string_binary(set_string.integer)} - {errors.to_string_binary(set_string._string)} - {errors.to_string_binary(set_string.array)}"); diff --git a/Public/ecma/ErrorsManager.ecma.js b/Public/ecma/ErrorsManager.ecma.js index b733879..aff6230 100644 --- a/Public/ecma/ErrorsManager.ecma.js +++ b/Public/ecma/ErrorsManager.ecma.js @@ -1,28 +1,36 @@ "use strict"; /** - * @class + * @class ErrorsManager * @constructor - * @param {string|Array.} [alphabet] + * @param {?(Object.|Array.|string)} [inputs = null] * @returns {void} * @access public + * @static */ export const ErrorsManager = (function(){ - + /** * @constructs ErrorsManager - * @param {string|Array.} [alphabet] + * @param {?(Object.|Array.|string)} [inputs = null] * @returns {void} * @access private + * @static */ - const ErrorsManager = function(alphabet){ + const ErrorsManager = function(inputs = null){ /** @type {ErrorsManager} */ - const self = this; + const self = this, + /** @type {Array.} */ + alphabet = [], + /** @type {Object.} */ + dictionary = {}; /** @type {number} */ - let error = 0; - // /** @type {RegExp|null} */ - // let re_hexa_error = null; + let error = 0, + /** @type {number} */ + base, + /** @type {number} */ + power; /** * @returns {void} @@ -30,479 +38,706 @@ export const ErrorsManager = (function(){ */ const constructor = () => { - self.set_alphabet(alphabet); + self.set_alphabet( + ErrorsManager.get("alphabet", inputs, ErrorsManager.ALPHABET), + ErrorsManager.get("base", inputs, 64) + ); }; /** - * @param {!(string|Array.)} new_alphabet + * @param {?(string|Array.)} [new_alphabet = null] + * @param {!number} [new_base = 64] * @returns {number} * @access public */ - this.set_alphabet = new_alphabet => { + this.set_alphabet = (new_alphabet = null, new_base = 64) => { - error = ( - new_alphabet === undefined ? 0 : - new_alphabet === null ? 0 : - !ErrorsManager.is_string(new_alphabet) && !ErrorsManager.is_array(new_alphabet) ? 1 << 2 : - 0) << 1; + /** @type {number} */ + let original_length; - if(!error){ - if(new_alphabet){ + error = 0; + // alphabet.splice(0, alphabet.length); + alphabet.length = 0; - /** @type {number} */ - const original_length = new_alphabet.length, - /** @type {number} */ - final_length = (new_alphabet = (new_alphabet instanceof Array ? new_alphabet : new_alphabet.split("")).filter((character, i) => ( - ErrorsManager.is_string(character) && character.length == 1 && new_alphabet.indexOf(character) == i - ))).length; - - error |= ( - original_length != final_length ? 1 << 0 : - final_length < 64 ? 1 << 1 : - 0) << 5; - - }; + if(ErrorsManager.is_null_or_undefined(new_alphabet)) + alphabet.push(...ErrorsManager.ALPHABET); + else if(ErrorsManager.is_string(new_alphabet)) + alphabet.push(...new_alphabet.split("")); + else if(ErrorsManager.is_array(new_alphabet)) + alphabet.push(...new_alphabet); + else{ + error |= 1 << 2; + alphabet.push(...ErrorsManager.ALPHABET); }; - alphabet = error || !new_alphabet ? ( - alphabet && alphabet.length ? alphabet : - ErrorsManager.BASE64) : new_alphabet; - // re_hexa_error = new RegExp("[^" + alphabet[0] + "]"); + original_length = alphabet.length; + + for(let i = alphabet.length - 1; i >= 0; i--) + alphabet.indexOf(alphabet[i]) != i && alphabet.splice(i, 1); + + if(alphabet.length < 2){ + error |= 1 << 3; + alphabet.splice(0, alphabet.length); + alphabet.push(...ErrorsManager.ALPHABET); + }; + if(alphabet.length != original_length) + error |= 1 << 4; + if(alphabet.length > 128) + error |= 1 << 5; + + error |= ( + new_base < 2 ? 1 << 0 : + new_base > 128 ? 1 << 1 : + new_base >= alphabet.length ? 1 << 2 : + 0) << 6; + + if(!(error >> 6)) + alphabet.splice(new_base, alphabet.length - new_base); + + alphabet.splice(base = 2 ** (power = Math.log2(alphabet.slice(0, 128).length) >> 0)); + + for(const key in dictionary) + delete dictionary[key]; + + for(let i = alphabet.length - 1; i >= 0; i--) + dictionary[alphabet[i]] = i; return error; }; /** - * @param {!(string|number|Array.)} code - * @param {!number} [length = 0] - * @returns {Array.} - * @access public - */ - this.to_array = (code, length = 0) => { - - /** @type {Array.} */ - let array = []; - - if(ErrorsManager.is_string(code)) - array = code.split("").map(hexa => alphabet.indexOf(hexa)); - else if(ErrorsManager.is_integer(code)){ - while(code){ - array.push(code & 0x3F); - code >>>= 6; - }; - }else if(ErrorsManager.is_array(code)) - array = [].concat(code); - - while(array.length < length) - array.push(0); - - return array && array.length ? array : [0]; - }; - - /** - * @param {!(number|string|Array.)} error - * @param {!Array.} [messages = []] - * @returns {Array.} - * @access public - */ - this.process = (error, messages = []) => { - - /** @type {Array.} */ - const response = [], - /** @type {number} */ - m = messages.length, - /** @type {Array.} */ - array_error = self.to_array(error), - /** @type {number} */ - l = array_error.length; - - for(let i = 0; i < l; i ++) - for(let j = 0; j < 6; j ++) - if(array_error[i] & (1 << j)){ - - /** @type {number} */ - const k = j + i * 6; - - response.push([k, k < m && messages[k] ? messages[k] : "error_message_" + k]); - - }; - - return response; - }; - - /** - * @returns {Array.} + * @returns {string} * @access public */ this.get_alphabet = () => alphabet.join(""); /** - * @param {!(string|number|Array.)} code - * @returns {number} + * @param {!(string|Array.|number)} code + * @return {Array.} * @access public */ - this.bits = code => { - if(ErrorsManager.is_integer(code)) - return code ? Math.log2(code) : 1; - - ErrorsManager.is_string(code) && (code = self.to_array(code)); - + this.to_array = code => { + if(ErrorsManager.is_string(code)) + return code.split("").map(character => dictionary[character]); if(ErrorsManager.is_array(code)) - return !(code = self.compact(code)).length || !code[code.length - 1] ? 1 : (code.length - 1) * 6 + (Math.log2(code[code.length - 1]) + 1 >> 0); - return null; + return code; + if(ErrorsManager.is_integer(code)){ + + /** @type {Array.} */ + const hexas = []; + + while(code){ + hexas.push(code % base); + code = code / base >> 0; + }; + + return hexas; + }; + return []; }; /** - * @param {!(string|number|Array.)} code - * @returns {Array.} + * @param {!(string|Array.|number)} code + * @return {string} * @access public */ - this.to_array_binary = code => (code = self.to_array(code)).map(hexa => ("000000" + hexa.toString(2)).slice(-6)); + this.to_string = code => { + if(ErrorsManager.is_string(code)) + return code; + if(ErrorsManager.is_array(code)) + return code.map(number => alphabet[number]).join(""); + if(ErrorsManager.is_integer(code)){ + + /** @type {string} */ + let string = ""; + + while(code){ + string += alphabet[code % base]; + code = code / base >> 0; + }; + + return string; + }; + return ""; + }; /** - * @param {!(string|number|Array.)} code - * @returns {number} + * @param {!(string|Array.|number)} code + * @return {number} * @access public */ this.to_integer = code => { - if(ErrorsManager.is_integer(code)) - return code; - if(ErrorsManager.is_array(code)) - return code.length ? code.length > 1 ? code.reduce((total, hexa, i) => total | (hexa << i * 6)) : code[0] : 0; - if(!ErrorsManager.is_string(code)) - return 0; - return code ? code.length > 1 ? code.split("").reduce((total, hexa, i) => (i > 1 ? total : alphabet.indexOf(total)) | (alphabet.indexOf(hexa) << i * 6)) : alphabet.indexOf(code) : 0; - }; - - /** - * @param {!(string|number|Array.)} code - * @param {!number} [length = 0] - * @returns {string} - * @access public - */ - this.to_string = (code, length = 0) => { - - /** @type {string} */ - let string = ""; - if(ErrorsManager.is_string(code)) - string = code; - else{ - if(ErrorsManager.is_integer(code)){ - while(code){ - string += alphabet[code & 0x3F]; - code >>>= 6; - }; - }else if(ErrorsManager.is_array(code)) - string = code.length ? code.length > 1 ? code.reduce((total, hexa, i) => (i > 1 ? total : alphabet[total]) + alphabet[hexa]) : alphabet[code[0]] : alphabet[0]; - }; - - while(string.length < length) - string += alphabet[0]; - - return string || alphabet[0]; - }; - - /** - * @param {!(string|number|Array.)} code - * @param {!(number|Array.)} [bits] - * @returns {boolean|null} - * @access public - */ - this.has = (code, bits) => { - if(!ErrorsManager.is_integer(bits) && !ErrorsManager.is_array(bits)) - return ( - ErrorsManager.is_string(code) ? code.split("").some(hexa => hexa != alphabet[0]) : - ErrorsManager.is_integer(code) ? !!code : - ErrorsManager.is_array(code) ? code.some(hexa => !!hexa) : - null); - - /** @type {Array.} */ - const error = self.to_array(code), - /** @type {number} */ - l = error.length * 6; - - return l ? ( - AnP.is_array(bits) ? bits : [bits] - ).some(bit => bit <= l && error[bit / 6 >> 0] & (1 << bit % 6)) : false; - }; - - /** - * @param {?any} code - * @returns {any|null} - * @access public - */ - this.to_unknown = code => code; - - /** - * @param {!(string|number|Array.)} code - * @returns {string|number|Array.} - * @access public - */ - this.compact = code => { - if(ErrorsManager.is_string(code)){ - while(code && code[code.length - 1] == alphabet[0]) - code = code.substr(0, code.length - 1); - return code || alphabet[0]; - }; - if(ErrorsManager.is_array(code)){ - code = [].concat(code); - while(code.length && !code[code.length - 1]) - code.pop(); - return code.length ? code : [0]; - }; + return code.split("").reduce((integer, character) => integer * base + dictionary[character], 0); + if(ErrorsManager.is_array(code)) + return code.reduce((integer, number) => integer * base + number, 0); if(ErrorsManager.is_integer(code)) return code; return 0; }; /** - * @param {!(string|number|Array.)} code + * @param {!(string|Array.|number)} code + * @return {string} + * @access public + */ + this.to_string_binary = code => { + if(ErrorsManager.is_string(code)) + return code.split("").map(character => dictionary[character].toString(2).padStart(power, "0")).join(""); + if(ErrorsManager.is_array(code)) + return code.map(number => number.toString(2).padStart(power, "0")).join(""); + if(ErrorsManager.is_integer(code)){ + + /** @type {string} */ + let string = ""; + + while(code){ + string = (code % base).toString(2).padStart(power, "0") + string; + code = code / base >> 0; + }; + + return string; + }; + return ""; + }; + + /** + * @param {!(string|Array.|number)} code + * @return {number} + * @access public + */ + this.get_bits = code => { + if(ErrorsManager.is_string(code)) + return (code.length - 1) * power + Math.ceil(Math.log2(dictionary[code[code.length - 1]] + 1)); + if(ErrorsManager.is_array(code)) + return (code.length - 1) * power + Math.ceil(Math.log2(code[code.length - 1] + 1)); + if(ErrorsManager.is_integer(code)) + return Math.ceil(Math.log2(code + 1)); + return 0; + }; + + /** + * @param {!Array.} code + * @param {!number} from * @param {!number} bits - * @returns {string|number|Array.} + * @returns {![number, number]} + * @access private + */ + const get_from_bits_array = (code, from, bits) => { + + if(from < 0){ + from = self.get_bits(code) + from; + if(from < 0) + from = 0; + }; + if(bits < 0){ + from += bits; + bits *= -1; + if(from < 0){ + bits += from; + from = 0; + }; + }; + + return [from, bits]; + }; + + /** + * @param {!(string|Array.|number)} code + * @param {!number} from + * @param {!number} bits + * @returns {![number, number]} + * @access public + */ + this.get_from_bits = (code, from, bits) => ( + ErrorsManager.is_string(code) ? get_from_bits_array(code.split("").map(character => dictionary[character]), from, bits) : + ErrorsManager.is_array(code) ? get_from_bits_array(code, from, bits) : + ErrorsManager.is_integer(code) ? get_from_bits_array(self.to_array(code), from, bits) : + [from, bits]); + + /** + * @param {!(string|Array.|number)} code + * @returns {string|Array.|number|null} + * @access public + */ + this.clean = code => { + if(ErrorsManager.is_string(code)){ + + /** @type {number} */ + let l = code.length; + + for(; l > 0 && code[l - 1] == alphabet[0]; l --); + + return ( + l == code.length ? code : + !l ? alphabet[0] : + code.slice(0, l)); + }; + if(ErrorsManager.is_array(code)){ + + /** @type {number} */ + let l = code.length; + + for(; l > 0 && code[l - 1] == 0; l --); + + return ( + l == code.length ? code : + !l ? [0] : + code.slice(0, l)); + }; + if(ErrorsManager.is_integer(code)) + return code; + return null; + }; + + /** + * @param {!(string|Array.|number)} code + * @param {!number} from + * @param {!number} bits + * @returns {!(string|Array.|number|null)} + * @access public + */ + this.get_range = (code, from, bits) => { + if(ErrorsManager.is_array(code)){ + + /** @type {Array.} */ + const hexas = []; + + [from, bits] = self.get_from_bits(code, from, bits); + + if(bits == 0) + bits = self.get_bits(code) - from; + if(bits <= 0) + return [0]; + + hexas.push(...code); + + if(from > 0){ + + /** @type {number} */ + const shift = from % power, + /** @type {number} */ + mask = ~-base; + + hexas = hexas.slice(from / power >> 0); + if(shift != 0 && hexas.length){ + + /** @type {number} */ + const l = hexas.length - 1; + + for(let i = 0; i < l; i ++) + hexas[i] = ((hexas[i] >> shift) | (hexas[i + 1] << power - shift)) & mask; + hexas[l] >>= shift; + + }; + + } + if(bits > 0){ + + /** @type {number} */ + const shift = bits % power, + /** @type {number} */ + l = Math.ceil(bits / power); + + hexas = hexas.slice(l, hexas.length - l); + if(shift && hexas.length) + hexas[hexas.length - 1] &= ~(-1 << shift); + + }; + + return self.clean(hexas); + }; + if(ErrorsManager.is_string(code)) + return self.to_string(self.get_range(self.to_array(code), from, bits)); + if(ErrorsManager.is_integer(code)){ + + [from, bits] = self.get_from_bits(code, from, bits); + + from > 0 && (code = (code >> from) & ~-(1 << 31 - from)); + + if(bits <= 0 || bits >= 31) + return code; + + from + bits > 31 && (bits = 31 - from); + + return code & ~-(1 << bits); + }; + return null; + }; + + /** + * @param {!(string|Array.|number)} code + * @param {!Array.} messages + * @param {?Object.} [blocks = null] + * @returns {Array.<[number, string]>} + * @access public + */ + this.process = (code, messages, blocks = null) => { + + /** @type {Array.<[number, string]>} */ + const response = [], + /** @type {number} */ + l = (code = self.to_array(code)).length; + /** @type {number} */ + let k = 0; + + blocks || (blocks = {}); + + for(let i = 0; i < l;) + if(blocks[i] !== undefined){ + + /** @type {number} */ + const logarithm = Math.log2(blocks[i]) >> 0; + /** @type {number} */ + let _k = self.to_integer(self.get_range(code, i, logarithm ? logarithm : logarithm = 1)); + + if(_k > 0){ + _k = k + _k; + response.push([k, messages[k] || "error_message_" + k]); + }; + + k += blocks[i]; + i += logarithm; + + }else{ + code[i / power >> 0] & (1 << i % power) && response.push([k, messages[k] || "error_message_" + k]); + k ++; + i ++; + }; + + return response; + }; + + /** + * @param {!(string|Array.|number)} code + * @param {!number} bits + * @return {string|Array.|number|null} * @access public */ this.bitwise = (code, bits) => { - - if(!bits || !self.has(code)) - return code; - - - /** @type {boolean} */ - const reverse = bits < 0, - /** @type {number} */ - start = (reverse ? bits *= -1 : bits) / 6 >> 0, - /** @type {number} */ - rest = bits % 6, - /** @type {string} */ - type_method = "to_" + ErrorsManager.type(code); - - if(reverse){ - - code = self.to_string(code).substring(start); - - if(rest){ - if(code){ - - /** @type {number} */ - const l = (code = self.to_array(code)).length - 1, - /** @type {number} */ - r = 6 - rest, - /** @type {number} */ - block = ~-(1 << rest); - - for(let i = 0; i < l; i ++) - code[i] = (code[i] >> rest) | ((code[i + 1] & block) << r); - code[l] >>= rest; - - }else - code = [0]; - }; - - }else{ - - code = self.to_array(code); - - if(rest){ - - /** @type {number} */ - const r = 6 - rest, - /** @type {Array.} */ - block = [~-(1 << r), ~-(1 << rest) << r], - /** @type {number} */ - l = code.length - 1, - /** @type {number} */ - last = (code[l] & block[1]) >> r; - - last && (code[l + 1] = last); - for(let i = l; i > 0; i --) - code[i] = ((code[i] & block[0]) << rest) | (code[i - 1] >> r); - code[0] = (code[0] & block[0]) << rest; - - }; - - for(let i = 0; i < start; i ++) - code.unshift(0); - - }; - - return self[type_method](code); - }; - - /** - * @param {!(string|number|Array.)} code - * @param {!(string|number|Array.)} error - * @param {!number} [bit = 0] - * @param {!number} [length = 0] - * @returns {string} - * @access public - */ - this.set = (code, error, bit = 0, length = 0) => { - - code = self.to_array(code); - error = self.to_array(error); - bit && (error = self.bitwise(error, bit)); - - /** @type {number} */ - let i = bit / 6 >> 0; - - if(length){ - - /** @type {Array.} */ - const ampersand = [], - /** @type {number} */ - start = bit % 6, - /** @type {number} */ - m = (length + start) / 6 >> 0, - /** @type {number} */ - end = (start + length) % 6; - - for(let j = 0; j < m; j ++) - ampersand.push(0); - ampersand[0] |= ~-(1 << start); - end && ampersand.push(~-(1 << (6 - end)) << end); - - ampersand.forEach((hexa, j) => code[j + i] &= hexa); - - }; - - if(self.has(error)){ + if(ErrorsManager.is_array(code)){ + if(!code.length || !bits) + return code; /** @type {number} */ - const l = error.length; + const shift = Math.abs(bits) % power, + /** @type {number} */ + mask = ~-base, + /** @type {Array.} */ + hexas = [...code]; + if(bits < 0){ - while(code.length <= i) - code.push(0); + hexas.splice(0, -bits / power >> 0); + if(shift != 0 && hexas.length){ - for(; i < l; i ++) - code[i] = (code[i] || 0) | error[i]; + /** @type {number} */ + const l = hexas.length - 1; + for(let i = 0; i < l; i ++) + hexas[i] = (hexas[i] >> shift | (hexas[i + 1] << power - shift)) & mask; + hexas[l] >>= shift; + + }; + + }else{ + + if(shift != 0){ + + /** @type {number} */ + const last_hexa = hexas[hexas.length - 1] << shift; + + for(let i = hexas.length - 1; i > 0; i --) + hexas[i] = ((hexas[i] << shift) | (hexas[i - 1] >> power - shift)) & mask; + hexas[0] = (hexas[0] << shift) & mask; + + if(last_hexa) + hexas.push(last_hexa); + + }; + + for(let i = bits / power >> 0; i > 0; i --) + hexas.unshift(0); + + }; + + return self.clean(hexas); }; - - return self.compact(self.to_string(code)); + if(ErrorsManager.is_string(code)) + return self.to_string(self.bitwise(self.to_array(code), bits)); + if(ErrorsManager.is_integer(code)){}; + return null; }; /** - * @param {!(string|number|Array.)} code - * @param {!(string|number|Array.)} error - * @param {!number} [bit = 0] - * @param {!number} [length = 0] - * @returns {string} + * @param {!(string|Array.|number)} code + * @param {!number} from + * @param {!number} bits + * @param {!boolean} reversed + * @returns {!(string|Array.|number|null)} * @access public */ - this.join = (code, error, bit = 0, length = 0) => self.set(code, error, bit, length); - - /** - * @param {!(string|number|Array.)} code - * @param {!Array.>} blocks - * @param {!number} [bit = 0] - * @param {!number} [length = 0] - * @returns {string} - * @access public - */ - this.set_blocks = (code, blocks, bit = 0, length = 0) => { + this.reset = (code, from, bits = 0, reversed = false) => { + if(ErrorsManager.is_array(code)){ - /** @type {number} */ - const l = blocks.length; + /** @type {Array.} */ + const hexas = [...code]; + /** @type {[number, number, number]} */ + let l, from_mask, to_mask; - length && (code = self.set(code, 0, bit, length)); + [from, bits] = self.get_from_bits(hexas, from, bits); - for(let i = 0; i < l; i ++) - blocks[i] && (code = self.set(code, blocks[i], bit)); + /** @type {number} */ + const hexa_from = from / power >> 0, + /** @type {number} */ + hexas_to = Math.ceil((from + bits) / power); - return code || alphabet[0]; + if(reversed){ + + l = from % power; + from_mask = ~-(1 << power) << l; + to_mask = ~-(1 << (from + bits) % power); + + for(let i = 0, l = hexas.length; i < l; i ++) + if(i < hexa_from || i > hexas_to) + hexas[i] = 0; + + if(hexa_from == hexa_to) + hexas[hexa_to] &= from_mask | to_mask; + else{ + hexas[hexa_from] &= from_mask; + if(hexa_to < hexas.length) + hexas[hexa_to] &= to_mask; + }; + + }else{ + + l = (from + bits) % power; + from_mask = ~-(1 << from % power); + to_mask = ~-(1 << l) << l; + + if(hexa_from == hexa_to) + hexas[hexa_to] &= from_mask | to_mask; + else{ + hexas[hexa_from] &= from_mask; + for(let i = hexa_from + 1; i < hexas_to && i < hexas.length; i ++) + hexas[i] = 0; + if(hexa_to < hexas.length) + hexas[hexa_to] &= to_mask; + }; + + }; + + return self.clean(hexas); + }; + if(ErrorsManager.is_string(code)) + return self.to_string(self.reset(self.to_array(code), from, bits, reversed)); + if(ErrorsManager.is_integer(code)){ + + [from, bits] = self.get_from_bits(code, from, bits); + from + bits > 31 && (bits = 31 - from); + + return code & ( + reversed ? ~-(1 << bits) << from : + (~-(1 << self.get_bits(code)) << from + bits) | ~-(1 << from)); + }; + return null; }; /** - * @param {!(string|number|Array.)} code - * @param {!number} _from - * @param {!number} [_to = 0] - * @returns {string|number|Array.|null} + * @param {!(string|Array.|number)} code + * @param {!number} from + * @param {!number} bits + * @return {boolean|null} * @access public */ - this.slice = (code, _from, _to = 0) => { - if(!self.has(code)) - return code; - - /** @type {number} */ - const bits = self.bits(code); - /** @type {number} */ - let rest; - - _from < 0 && (_from = bits + _from); - _to = ( - _to > bits ? bits : - _to < 0 ? bits - _to : - _to) - _from; - rest = _to % 6; - code = self.bitwise(code, -_from); - - return ( - ErrorsManager.is_string(code) ? code.slice(0, _to / 6 >> 0) + (rest ? alphabet[alphabet.indexOf(code.slice(-1)) & ~-(1 << rest)] : "") : - ErrorsManager.is_array(code) ? code.slice(0, _to / 6 >> 0).concat(rest ? [code[code.length - 1] & ~-(1 << rest)] : []) : - ErrorsManager.is_integer(code) ? code & ~-(1 << _to) : - null); - }; + this.has = (code, from = 0, bits = 0) => ( + ErrorsManager.is_string(code) ? self.get_range(code, from, bits).split("").some(character => character != alphabet[0]) : + ErrorsManager.is_array(code) ? self.get_range(code, from, bits).some(number => number != 0) : + ErrorsManager.is_integer(code) ? !!self.get_range(code, from, bits) : + null); /** - * @param {!(string|number|Array.)} code - * @param {!number} _from - * @param {!number} [_to = 0] - * @returns {boolean} + * @param {!(string|Array.|number)} error + * @param {!(string|Array.|number)} code + * @param {!number} from + * @param {!number} bits + * @return {string|Array.|number|null} * @access public */ - this.has_range = (code, _from, _to = 0) => self.has(self.slice(code, _from, _to)); + this.set = (error, code, from = 0, bits = 0) => { + if(ErrorsManager.is_array(code)){ + + let l, + m = error.length, + n = code.length; + const results = []; + + bits && (m = (error = self.reset(error, from, bits)).length); + from && (n = (code = self.bitwise(code, from)).length); + l = m > n ? m : n; + + for(let i = 0; i < l; i ++) + results.push( + (i < m ? error[i] : 0) | + (i < n ? code[i] : 0) + ); + + return self.clean(results); + }; + if(ErrorsManager.is_string(code)) + return self.to_string(self.set(self.to_array(error), self.to_array(code), from, bits)); + if(ErrorsManager.is_integer(code)){ + + bits && (error = self.reset(error, from, bits)); + from && (code = self.bitwise(code, from)); + + return error | code; + }; + return null; + }; constructor(); }; /** @type {Array.} */ - ErrorsManager.BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split(""); + ErrorsManager.ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split(""); + + /** @type {Array.} */ + ErrorsManager.ERRORS_MESSAGES = [ + "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" + ]; + + /** @type {RegExp} */ + ErrorsManager.RE_KEY = /^[a-z_][a-z0-9_]*$/i; /** - * @param {?any} value + * @param {?any} item * @returns {boolean} * @access public * @static */ - ErrorsManager.is_string = value => typeof value == "string"; + ErrorsManager.is_array = item => item instanceof Array; /** - * @param {?any} value + * @param {?any} item * @returns {boolean} * @access public * @static */ - ErrorsManager.is_integer = value => typeof value == "number" && value == value >> 0; + ErrorsManager.is_dictionary = item => item instanceof Object && item.constructor === Object; /** - * @param {?any} value + * @param {?any} item * @returns {boolean} * @access public * @static */ - ErrorsManager.is_array = value => typeof value == "object" && value instanceof Array; + ErrorsManager.is_string = item => typeof item == "string"; /** - * @param {!(string|number|Array.)} code - * @returns {string} + * @param {?any} item + * @returns {boolean} * @access public * @static */ - ErrorsManager.type = code => { + ErrorsManager.is_key = item => ErrorsManager.is_string(item) && ErrorsManager.RE_KEY.test(item); + + /** + * @param {?any} item + * @returns {boolean} + * @access public + * @static + */ + ErrorsManager.is_integer = item => typeof item == "number" && item >> 0 == item; + + /** + * @param {?any} item + * @returns {boolean} + * @access public + * @static + */ + ErrorsManager.is_null_or_undefined = item => item === undefined || item === null; + + /** + * @param {?any} inputs + * @returns {Array.} + * @access public + * @static + */ + ErrorsManager.get_keys = inputs => { /** @type {Array.} */ - const types = ["string", "integer", "array"]; + const keys = []; - for(let i = 0; i < 3; i ++) - if(ErrorsManager["is_" + types[i]](code)) - return types[i]; - return "unknown"; + if(ErrorsManager.is_key(inputs)) + keys.push(inputs); + else if(ErrorsManager.is_array(inputs)) + for(const item of inputs) + ErrorsManager.get_keys(item).forEach(key => { + keys.includes(key) || keys.push(key); + }) + + return keys; }; + /** + * @param {?any} inputs + * @returns {Array.>} + * @access public + * @static + */ + ErrorsManager.get_dictionaries = inputs => { + + /** @type {Array.>} */ + const dictionaries = []; + + if(ErrorsManager.is_dictionary(inputs)) + dictionaries.push(inputs); + else if(ErrorsManager.is_array(inputs)) + for(const item of inputs) + dictionaries.push(...ErrorsManager.get_dictionaries(item)); + + return dictionaries; + }; + + /** + * @param {!(string|Array.)} keys + * @param {?any} inputs + * @param {?any} [_default = null] + * @returns {any|null} + * @access public + * @static + */ + ErrorsManager.get = (keys, inputs, _default = null) => { + if((keys = ErrorsManager.get_keys(keys)).length) + for(const dictionary of ErrorsManager.get_dictionaries(inputs)) + for(const key of keys) + if(key in dictionary) + return dictionary[key]; + return _default; + }; + + /** + * @param {!(string|Array.)} items + * @returns {string|Array.} + * @access public + * @static + */ + ErrorsManager.unique = items => ( + ErrorsManager.is_array(items) ? items.filter((item, i) => items.indexOf(item) == i) : + items.split("").filter((item, i) => items.indexOf(item) == i).join("")); + return ErrorsManager; })(); \ No newline at end of file diff --git a/Public/ecma/Tests.ecma.js b/Public/ecma/Tests.ecma.js new file mode 100644 index 0000000..5c03287 --- /dev/null +++ b/Public/ecma/Tests.ecma.js @@ -0,0 +1,434 @@ +"use strict"; + +import {ErrorsManager} from "./ErrorsManager.ecma.js"; + +/** + * @typedef {import("./ErrorsManager.ecma.js").ErrorsManager} ErrorsManager + */ + +/** + * @class FullError + * @constructor + * @returns {void} + * @access public + * @static + */ +export const FullError = (function(){ + + /** + * @constructs FullError + * @param {!ErrorsManager} errors + * @param {!(string|Array.|number)} code + * @returns {void} + * @access private + * @static + */ + const FullError = function(errors, code){ + + /** @type {FullError} */ + const self = this; + + /** @type {number} */ + this.integer = 0; + /** @type {string} */ + this.string = ""; + /** @type {Array.} */ + this.array = []; + + /** + * @returns {void} + * @access public + */ + const constructor = () => { + if(ErrorsManager.is_string(code)){ + self.string = code; + self.integer = errors.to_integer(code); + self.array = errors.to_array(code); + }else if(ErrorsManager.is_array(code)){ + self.array = code; + self.integer = errors.to_integer(code); + self.string = errors.to_string(code); + }else if(ErrorsManager.is_integer(code)){ + self.integer = code; + self.string = errors.to_string(code); + self.array = errors.to_array(code); + }; + }; + + constructor(); + + }; + + /** + * @param {!Array.} array + * @returns {string} + * @access public + * @static + */ + FullError.print = array => "[" + array.join(", ") + "]"; + + return FullError; +})(); + +/** + * @class Tests + * @constructor + * @returns {void} + * @access public + * @static + */ +export const Tests = (function(){ + + /** + * @constructs Tests + * @returns {void} + * @access private + * @static + */ + const Tests = function(){}; + + /** + * @param {!number} from + * @param {!number} to + * @returns {!number} + * @access public + * @static + */ + Tests.random = (from, to) => Math.floor(Math.random() * (to - from + 1)) + from >> 0; + + /** + * @returns {void} + * @access public + * @static + */ + Tests.errors = () => { + + /** @type {ErrorsManager} */ + const errors = new ErrorsManager(), + /** @type {FullError} */ + error = new FullError(errors, 217934237), + /** @type {FullError} */ + reset = new 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); + + console.log(`RESET: from ${-5} bits ${12}`); + console.log(`INTEGER: ${errors.to_string_binary(error.integer)} - ${errors.to_string_binary(reset.integer)}`); + console.log(`STRING: ${errors.to_string_binary(error.string)} - ${errors.to_string_binary(reset.string)}`); + console.log(`ARRAY: ${errors.to_string_binary(error.array)} - ${errors.to_string_binary(reset.array)}`); + console.log(); + + }; + + /** + * @returns {void} + * @access public + * @static + */ + Tests.conversions = (tests = 10, inputs = null) => { + + /** @type {ErrorsManager} */ + const errors = new ErrorsManager(inputs); + + for(let i = 0; i < tests; i ++){ + + /** @type {FullError} */ + const error = new FullError(errors, Tests.random(0, 1 << 16)); + + console.log(`INTEGER: ${errors.to_integer(error.integer)}, ${errors.to_integer(error.string)}, ${errors.to_integer(error.array)}`); + console.log(`STRING: ${errors.to_string(error.integer)}, ${errors.to_string(error.string)}, ${errors.to_string(error.array)}`); + console.log(`ARRAY: ${FullError.print(errors.to_array(error.integer))}, ${FullError.print(errors.to_array(error.string))}, ${FullError.print(errors.to_array(error.array))}`); + console.log(); + + }; + + return errors; + }; + + Tests.alphabet = (tests = 10) => { + for(let i = 0; i < tests; i ++){ + + /** @type {ErrorsManager} */ + const errors = Tests.conversions(1, { + "base" : Tests.random(2, 128) + }); + + console.log(`^^^ ALPHABET: ${errors.get_alphabet()} ^^^`); + console.log(); + + }; + }; + + /** + * @returns {void} + * @access public + * @static + */ + Tests.bitwise = (tests = 10) => { + + /** @type {ErrorsManager} */ + const errors = new ErrorsManager(); + + for(let i = 0; i < tests; i ++){ + + /** @type {FullError} */ + const error = new FullError(errors, Tests.random(0, 1 << Tests.random(0, 16))), + /** @type {FullError} */ + shifted = new FullError(errors, 0), + /** @type {FullError} */ + unshifted = new FullError(errors, 0), + /** @type {number} */ + bitwise = Tests.random(-10, 10); + + console.log(`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); + + console.log(`INTEGER: ${errors.to_string_binary(error.integer)} - ${error.integer}`); + console.log(`STRING: ${errors.to_string_binary(error.string)} - ${error.string}`); + console.log(`ARRAY: ${errors.to_string_binary(error.array)} - ${FullError.print(error.array)}`); + console.log(`INTEGER: ${errors.to_string_binary(shifted.integer)} - ${shifted.integer}`); + console.log(`STRING: ${errors.to_string_binary(shifted.string)} - ${shifted.string}`); + console.log(`ARRAY: ${errors.to_string_binary(shifted.array)} - ${FullError.print(shifted.array)}`); + console.log(`INTEGER: ${errors.to_string_binary(unshifted.integer)} - ${unshifted.integer}`); + console.log(`STRING: ${errors.to_string_binary(unshifted.string)} - ${unshifted.string}`); + console.log(`ARRAY: ${errors.to_string_binary(unshifted.array)} - ${FullError.print(unshifted.array)}`); + console.log(); + + }; + + }; + + /** + * @returns {void} + * @access public + * @static + */ + Tests.bitwise_sucesive = (tests = 10) => { + + /** @type {ErrorsManager} */ + const errors = new ErrorsManager(), + /** @type {FullError} */ + error = new FullError(errors, Tests.random(0, 1 << 16)); + + console.log(`INTEGER: ${errors.to_string_binary(error.integer)} - ${error.integer}`); + console.log(`STRING: ${errors.to_string_binary(error.string)} - ${error.string}`); + console.log(`ARRAY: ${errors.to_string_binary(error.array)} - ${FullError.print(error.array)}`); + console.log(); + + for(let i = -tests; i < tests; i ++){ + + /** @type {FullError} */ + const shifted = new FullError(errors, 0); + + console.log(`BITWISE: ${i}`); + + shifted.integer = errors.bitwise(error.integer, i); + shifted.string = errors.bitwise(error.string, i); + shifted.array = errors.bitwise(error.array, i); + + + console.log(`INTEGER: ${errors.to_string_binary(shifted.integer)} - ${shifted.integer}`); + console.log(`STRING: ${errors.to_string_binary(shifted.string)} - ${shifted.string}`); + console.log(`ARRAY: ${errors.to_string_binary(shifted.array)} - ${FullError.print(shifted.array)}`); + console.log(); + + }; + + }; + + /** + * @returns {void} + * @access public + * @static + */ + Tests.bits = (tests = 10) => { + + /** @type {ErrorsManager} */ + const errors = new ErrorsManager(); + + for(let i = 0; i < tests; i++){ + + /** @type {FullError} */ + const error = new FullError(errors, Tests.random(0, 1 << Tests.random(0, 28))), + /** @type {number} */ + from_value = Tests.random(-15, 15), + /** @type {number} */ + bits_value = Tests.random(-13, 13), + /** @type {[number, number, number]} */ + from = [from_value, from_value, from_value], + /** @type {[number, number, number]} */ + bits = [bits_value, bits_value, bits_value]; + + [from[0], bits[0]] = errors.get_from_bits(error.integer, from[0], bits[0]); + [from[1], bits[1]] = errors.get_from_bits(error.string, from[1], bits[1]); + [from[2], bits[2]] = errors.get_from_bits(error.array, from[2], bits[2]); + + + console.log(`CODE: ${error.integer} - ${error.string} - ${FullError.print(error.array)}`); + console.log(`ERROR: ${errors.to_string_binary(error.integer)} - ${errors.get_bits(error.integer)} - ${errors.get_bits(error.string)} - ${errors.get_bits(error.array)}`); + console.log(`FROM: ${from_value} - ${from[0]}, ${from[1]}, ${from[2]}`); + console.log(`BITS: ${bits_value} - ${bits[0]}, ${bits[1]}, ${bits[2]}`); + console.log(); + + }; + + }; + + /** + * @returns {void} + * @access public + * @static + */ + Tests.reset = (tests = 10) => { + + /** @type {ErrorsManager} */ + const errors = new ErrorsManager(); + + for(let i = 0; i < tests; i ++){ + + /** @type {FullError} */ + const error = new FullError(errors, Tests.random(0, 1 << 28)), + /** @type {number} */ + from = Tests.random(-15, 15), + /** @type {number} */ + bits = Tests.random(-13, 13), + /** @type {FullError} */ + reset = new FullError(errors, 0); + + reset.integer = errors.reset(error.integer, from, bits); + reset.string = errors.reset(error.string, from, bits); + reset.array = errors.reset(error.array, from, bits); + + console.log(`RESET: from ${from} bits ${bits}`); + console.log(`INTEGER: ${errors.to_string_binary(error.integer)} - ${errors.to_string_binary(reset.integer)}`); + console.log(`STRING: ${errors.to_string_binary(error.string)} - ${errors.to_string_binary(reset.string)}`); + console.log(`ARRAY: ${errors.to_string_binary(error.array)} - ${errors.to_string_binary(reset.array)}`); + console.log(); + + }; + + }; + + /** + * @returns {void} + * @access public + * @static + */ + Tests.ranges = (tests = 10) => { + + /** @type {ErrorsManager} */ + const errors = new ErrorsManager(); + + for(let i = 0; i < tests; i ++){ + + /** @type {FullError} */ + const error = new FullError(errors, Tests.random(0, 1 << 28)), + /** @type {number} */ + from = Tests.random(-15, 15), + /** @type {number} */ + bits = Tests.random(-13, 13), + /** @type {FullError} */ + range = new FullError(errors, 0); + + console.log(`RANGE: from ${from} bits ${bits}`); + [from, bits] = errors.get_from_bits(error.string, from, bits); + console.log(`REAL: from ${from} bits ${bits}`); + + range.integer = errors.get_range(error.integer, from, bits); + range.string = errors.get_range(error.string, from, bits); + range.array = errors.get_range(error.array, from, bits); + + console.log(`INTEGER: ${errors.to_string_binary(error.integer)} - ${errors.to_string_binary(range.integer)}`); + console.log(`STRING: ${errors.to_string_binary(error.string)} - ${errors.to_string_binary(range.string)}`); + console.log(`ARRAY: ${errors.to_string_binary(error.array)} - ${errors.to_string_binary(range.array)}`); + console.log(); + + }; + + }; + + /** + * @returns {void} + * @access public + * @static + */ + Tests.has = (tests = 10) => { + + /** @type {ErrorsManager} */ + const errors = new ErrorsManager(); + + for(let i = 0; i < tests; i ++){ + + /** @type {FullError} */ + const error = new FullError(errors, Tests.random(0, 1 << 28)); + const from = Tests.random(-15, 15); + const bits = Tests.random(-13, 13); + + console.log(`HAS: from ${from} bits ${bits}`); + console.log(`INTEGER: ${errors.has(error.integer, from, bits)} - ${errors.to_string_binary(error.integer)} - ${errors.to_string_binary(errors.get_range(error.integer, from, bits))}`); + console.log(`STRING: ${errors.has(error.string, from, bits)} - ${errors.to_string_binary(error.string)} - ${errors.to_string_binary(errors.get_range(error.string, from, bits))}`); + console.log(`ARRAY: ${errors.has(error.array, from, bits)} - ${errors.to_string_binary(error.array)} - ${errors.to_string_binary(errors.get_range(error.array, from, bits))}`); + console.log(); + + }; + + }; + + /** + * @returns {void} + * @access public + * @static + */ + Tests.set = (tests = 10) => { + + /** @type {ErrorsManager} */ + const errors = new ErrorsManager(); + + for(let i = 0; i < tests; i ++){ + + /** @type {FullError} */ + const error = new FullError(errors, Tests.random(0, 1 << 15)), + /** @type {FullError} */ + value = new FullError(errors, Tests.random(0, 1 << 15)), + /** @type {number} */ + from = Tests.random(-15, 15), + /** @type {number} */ + bits = Tests.random(-13, 13), + /** @type {FullError} */ + set_integer = new FullError(errors, 0), + /** @type {FullError} */ + set_string = new FullError(errors, 0), + /** @type {FullError} */ + set_array = new FullError(errors, 0); + + set_integer.integer = errors.set(error.integer, value.integer, from, bits); + set_string.integer = errors.set(error.integer, value.string, from, bits); + set_array.integer = errors.set(error.integer, value.array, from, bits); + set_integer.string = errors.set(error.string, value.integer, from, bits); + set_string.string = errors.set(error.string, value.string, from, bits); + set_array.string = errors.set(error.string, value.array, from, bits); + set_integer.array = errors.set(error.array, value.integer, from, bits); + set_string.array = errors.set(error.array, value.string, from, bits); + set_array.array = errors.set(error.array, value.array, from, bits); + + console.log(`SET: from ${from} bits ${bits} to [${value.string}, ${FullError.print(value.array)}, ${value.integer}]`); + console.log(`ERROR: ${errors.to_string_binary(error.integer)} - VALUE: ${errors.to_string_binary(value.integer)}`); + console.log(`INTEGER: ${errors.to_string_binary(set_integer.integer)} - ${errors.to_string_binary(set_integer.string)} - ${errors.to_string_binary(set_integer.array)}`); + console.log(`STRING: ${errors.to_string_binary(set_string.integer)} - ${errors.to_string_binary(set_string.string)} - ${errors.to_string_binary(set_string.array)}`); + console.log(`ARRAY: ${errors.to_string_binary(set_array.integer)} - ${errors.to_string_binary(set_array.string)} - ${errors.to_string_binary(set_array.array)}`); + console.log(); + + }; + + }; + + return Tests; +})(); \ No newline at end of file diff --git a/Public/test.html b/Public/test.html deleted file mode 100644 index e5df401..0000000 --- a/Public/test.html +++ /dev/null @@ -1,77 +0,0 @@ - \ No newline at end of file diff --git a/Public/tests.html b/Public/tests.html new file mode 100644 index 0000000..64d615f --- /dev/null +++ b/Public/tests.html @@ -0,0 +1,28 @@ + + + + Tests - ErrorsManager + + + + + + GV9ZEFFAK + + \ No newline at end of file diff --git a/Python/Application/ErrorsManager.py b/Python/Application/ErrorsManager.py deleted file mode 100644 index a4c505b..0000000 --- a/Python/Application/ErrorsManager.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from Abstracts.Applications import ApplicationsAbstract -from Abstracts.AnPMap import AnP, Optional, Any -from os.path import abspath as path_absolute -from os.path import dirname as directory_name - -class ErrorsManager(ApplicationsAbstract): - - def __init__(self, anp:AnP|None, inputs:Optional[dict[str, Any|None]|tuple|list] = None) -> None: - super().__init__(anp, "errors_manager", anp.path.get_parent(path_absolute(directory_name(__file__))), { - **anp.get_dictionary(inputs), - "errors_manager_default_settings_files" : "/JSON/ErrorsManager.py.settings.json" - }) \ No newline at end of file diff --git a/Python/ErrorsManager.py b/Python/ErrorsManager.py index 6e342d2..1f776fc 100644 --- a/Python/ErrorsManager.py +++ b/Python/ErrorsManager.py @@ -1,396 +1,2 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from typing import Any, Optional -from math import log2 - -class ErrorsManager: - - BASE64:list[str] = [*"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="] - - def __init__(self, alphabet:Optional[str|list[str]|tuple[str]] = None) -> None: - - self.__error:int = 0 - # self.__re_hexa_error:REPattern|None = None - self.__alphabet:list[str] = [] - - self.set_alphabet(alphabet) - - @staticmethod - def is_string(value:Any|None) -> bool: - return isinstance(value, str) - - @staticmethod - def is_array(value:Any|None) -> bool: - return isinstance(value, (list, tuple)) - - @staticmethod - def is_integer(value:Any|None) -> bool: - return isinstance(value, int) - - def set_alphabet(self, alphabet:Optional[str] = None) -> int: - - self.__error = ( - 0 if alphabet == None else - 1 << 2 if not ErrorsManager.is_array(alphabet) and not ErrorsManager.is_string(alphabet) else - 0) << 1 - - if not self.__error: - if alphabet: - - original_length:int = len(self.__alphabet) - final_length:int = 0 - character:str - i:int - - alphabet = ( - alphabet if isinstance(alphabet, list) else - list(alphabet) if isinstance(alphabet, tuple) else - [*alphabet]) - alphabet = [character for i, character in alphabet if isinstance(character, str) and len(character) == 1 and alphabet.index(character) == i] - final_length = len(alphabet) - - self.__error |= ( - 1 << 0 if original_length != final_length else - 1 << 1 if final_length < 64 else - 0) << 5 - - self.__alphabet = ( - self.__alphabet if self.__alphabet and len(self.__alphabet) else - ErrorsManager.BASE64) if self.__error or not alphabet else alphabet - # self.__re_hexa_error = RECompile(r'[^' + alphabet[0] + ']') - - return self.__error - - def to_array(self, - code:str|int|list[int]|tuple[int], - length:Optional[int] = 1 - ) -> list[int]: - - array:list[int] = [] - - if ErrorsManager.is_string(code): - - hexa:str - - for hexa in code: - array += [self.__alphabet.index(hexa)] - - elif ErrorsManager.is_integer(code): - while code: - array += [code & 0x3F] - code >>= 6 - elif ErrorsManager.is_array(code): - - hexa:int - - for hexa in code: - array += [hexa] - - while len(array) < length: - array += [0] - - return array - - def process(self, - error:int|str|list[int]|tuple[int], - messages:list[str]|tuple[str] - ) -> list[str]: - - response:list[str] = [] - m:int = len(messages) - i:int - hexa:int - - for i, hexa in enumerate(self.to_array(error)): - - j:int - - for j in range(6): - if hexa & (1 << j): - - k:int = j + i * 6 - - response += [[k, messages[k] if k < m and messages[k] else "error_message_" + str(k)]] - - return response - - def get_alphabet(self) -> str: - return "".join(self.__alphabet) - - def bits(self, code:str|int|list[int]|tuple[int]) -> int|None: - - if ErrorsManager.is_integer(code): - return 1 if not code else int(log2(code) + 1) - - if ErrorsManager.is_string(code): - code = self.to_array(code) - - if ErrorsManager.is_array(code): - - code = self.compact(code) - - l:int = len(code) - - return 1 if not l or not code[-1] else (l - 1) * 6 + int(log2(code[-1]) + 1) - return None - - def get_error(self) -> int: - return self.__error | 0 - - def to_array_binary(self, code:str|int|list[int]|tuple[int]) -> list[str]: - - hexa:int - - return [("000000" + "{0:b}".format(hexa))[-6:] for hexa in self.to_array(code)] - - def to_integer(self, code:str|int|list[int]|tuple[int]) -> int: - if ErrorsManager.is_integer(code): - return code - if ErrorsManager.is_array(code): - - hexa:int - i:int - - return sum([hexa << i * 6 for i, hexa in enumerate(code)]) - if ErrorsManager.is_string(code): - - hexa:str - i:int - - return sum([self.__alphabet.index(hexa) << i * 6 for i, hexa in enumerate(code)]) - return 0 - - def to_string(self, - code:str|int|list[int]|tuple[int], - length:Optional[int] = 1 - ) -> str: - - string:str = "" - - if ErrorsManager.is_string(code): - string += code - elif ErrorsManager.is_integer(code): - while code: - string += self.__alphabet[code & 0x3F] - code >>= 6 - elif ErrorsManager.is_array(code): - - hexa:str - - string = "".join([self.__alphabet[hexa] for hexa in code]) - - while len(string) < length: - string += self.__alphabet[0] - - return string or self.__alphabet[0] - - def has(self, - code:int|str|tuple[int]|list[int], - bits:Optional[int|list[int]|tuple[int]] = None - ) -> bool: - if not ErrorsManager.is_integer(bits) and not ErrorsManager.is_array(bits): - if ErrorsManager.is_string(code): - - hexa:str - - for hexa in code: - if self.__alphabet.index(hexa): - return True - return False - if ErrorsManager.is_integer(code): - return not not code - if ErrorsManager.is_array(code): - - hexa:int - - for hexa in code: - if hexa: - return True - return False - - error:list[int] = self.to_array(code) - bit:int - - if ErrorsManager.is_integer(bits): - bits = (bits,) - - for bit in bits[:len(error) - 1]: - if error[bit]: - return True - return False - - def to_unknown(self, code:Any|None) -> Any|None: - return code - - def compact(self, code:int|str|list[int]|tuple[int]) -> int|str|list[int]: - if ErrorsManager.is_string(code): - while code and code[-1] == self.__alphabet[0]: - code = code[:-1] - return code or self.__alphabet[0] - if ErrorsManager.is_array(code): - code = list(code) - while len(code) and not code[-1]: - code = code[:-1] - return code if len(code) else [0] - if ErrorsManager.is_integer(code): - return code - return 0 - - @classmethod - def type(self, code:int|str|tuple[int]|list[int]): - return ( - "string" if self.is_string(code) else - "integer" if self.is_integer(code) else - "array" if self.is_array(code) else - "unknown") - - def bitwise(self, - code:int|str|tuple[int]|list[int], - bits:int - ) -> str|int|list[int]: - - if not bits or not self.has(code): - return code - - reverse:bool = bits < 0 - - if reverse: - bits *= -1 - - start:int = int(bits / 6) - rest:int = bits % 6 - type_method:str = "to_" + ErrorsManager.type(code) - - code = self.to_array(code) - - if reverse: - - code = code[start:] - - if rest: - if code: - - r:int = 6 - rest - block:int = ~-(1 << rest) - i:int - hexa:int - - code = [(hexa >> rest) | ((code[i + 1] & block) << r) for i, hexa in enumerate(code[:-1])] + [code[-1] >> rest] - - else: - code = [0] - - else: - - i:int - - if rest: - - r:int = 6 - rest - mask:int = ~-(1 << 6) - - code = [(code[0] << rest) & mask] + [((hexa << rest) & mask) | (code[i - 1] >> r) for i, hexa in enumerate(code[1:])] + [code[-1] >> r] - - for i in range(start): - code = [0] + code - - return getattr(self, type_method)(code) - - def set(self, - code:int|str|list[int]|tuple[int], - error:int|str|list[int]|tuple[int], - bit:Optional[int] = 0, - length:Optional[int] = 0 - ) -> str: - - code = self.to_array(code) - error = self.to_array(error) - - if bit: - error = self.bitwise(error, bit) - - i:int = int(bit / 6) - - if length: - - start:int = bit % 6 - j:int - hexa:int - end:int = (start + length) % 6 - - for j, hexa in enumerate([~-(1 << start)] + [0 for j in range(int((length + start) / 6) - 1)] + ([~-(1 << (6 - end)) << end] if end else [])): - code[j + i] &= hexa - - if self.has(error): - - l:int = len(error) - - while len(code) < i: - code += [0] - - m:int = len(code) - - while i < l: - if i >= m: - code += [0] - code[i] = (code[i] or 0) | error[i] - i += 1 - - return self.compact(self.to_string(code)) - - def join(self, - code:int|str|list[int]|tuple[int], - error:int|str|list[int]|tuple[int], - bit:Optional[int] = 0, - length:Optional[int] = 0 - ) -> str: - return self.set(code, error, bit, length) - - def set_blocks(self, - code:str|int|tuple[int]|list[int], - blocks:list[str|int|tuple[int]|list[int]]|tuple[str|int|tuple[int]|list[int]], - bit:Optional[int] = 0, - length:Optional[int] = 0 - ) -> str: - - block:int - i:int - - if length: - code = self.set(code, 0, bit, length) - - for i, block in blocks: - if block: - code = self.set(code, block, i + bit) - - return code or self.__alphabet[0] - - def slice(self, - code:str|int|list[int]|tuple[int], - _from:int, - _to:Optional[int] = 0 - ) -> str|int|list[int]|None: - if self.has(code): - return code - - bits:int = self.bits(code) - rest:int - - if _from < 0: - _from = bits + _from - _to = ( - bits if _to > bits else - bits - _to if _to < 0 else - _to) - _from - rest = _to %6 - code = self.bitwise(code, -_from) - - return ( - code[:int(_to / 6)] + (self.__alphabet[self.__alphabet.index(code[-1]) & ~-(1 << rest)] if rest else "") if ErrorsManager.is_string(code) else - code[:int(_to / 6)] + ([code[-1] & ~-(1 << rest)] if rest else []) if ErrorsManager.is_array(code) else - code & ~-(1 << _to) if ErrorsManager.is_integer(code) else - None) - - def has_range(self, code:int|str|list[int]|tuple[int], _from:int, _to:Optional[int] = 0) -> bool: - return self.has(self.slice(code, _from, _to)) \ No newline at end of file +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- \ No newline at end of file diff --git a/Python/tests.py b/Python/tests.py deleted file mode 100644 index 7c2cdfb..0000000 --- a/Python/tests.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from ErrorsManager import ErrorsManager -from json import dumps as json_encode - -errors_manager:ErrorsManager = ErrorsManager() - -print(errors_manager.to_string(105)) -print(errors_manager.to_array(105)) -print(errors_manager.to_array_binary(105)) -print(errors_manager.process(105, ["error_message_" + str(i) for i, _ in enumerate("0123456789abcdef")])) - - -print(errors_manager.bits(105)) -print(errors_manager.bits("pB")) -print(errors_manager.bits([41, 1])) - -options = [-10, -5, -3, -1, 0, 1, 3, 5, 10] -filler = "" -results = [] - -while len(filler) < 30: - filler += " " - -def format(value, characters): - return " " + ( - json_encode(value).replace(",", ", ") + filler - )[:characters] - -for i, value in enumerate([105, "pB", [41, 1]]): - for bits in options: - - new_value = errors_manager.bitwise(value, bits) - example = [ - format(value, 7), - format(errors_manager.to_array_binary(value), 20), - format(bits, 4), - format(new_value, 12), - format(errors_manager.to_array_binary(new_value), 30) - ] - - results += [example] - - print(example) - - print("") - -# [105, "pB", [41, 1]].forEach((value, i) => options.forEach(bits => { - -# const new_value = errors_manager.bitwise(value, bits) - -# results.push([ -# format(value, 7), -# format(errors_manager.to_array_binary(value), 20), -# format(bits, 4), -# format(new_value, 12), -# format(errors_manager.to_array_binary(new_value), 30) -# ]) -# // print(results[results.length - 1]) - -# })) - -# -- print(results) -# // print(results.map(result => result.join("|")).join("\n")) \ No newline at end of file diff --git a/Python/v2/ErrorsManager.py b/Python/v2/ErrorsManager.py deleted file mode 100644 index 7e3cc16..0000000 --- a/Python/v2/ErrorsManager.py +++ /dev/null @@ -1,254 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from typing import Self, Any, Optional, Sequence -from math import log2 -from re import compile as re_compile, Pattern as REPattern, IGNORECASE as RE_IGNORE_CASE - -class ErrorsManager: - - RE_KEY:REPattern = re_compile(r'^[a-z_][a-z0-9_]*$', RE_IGNORE_CASE) - - def __init__(self:Self, inputs:Optional[str|dict[str, Any|None]|Sequence[Any|None]] = None) -> None: - - alphabet:str|Sequence[str] = self.unique(self.get_value("alphabet", ( - inputs := {"alphabet" : inputs} if isinstance(inputs, str) else - inputs), "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=")) - maximum_base:int = int(log2(len(alphabet))) - - self.__alphabet:tuple[str] = ( - tuple(alphabet) if isinstance(alphabet, (list, str)) else - alphabet) - self.__alphabet_map:dict[str, int] = {character : i for i, character in enumerate(self.__alphabet)} - self.__base:int = self.get_value("base", inputs, maximum_base) - self.__mask:int - - if self.__base > maximum_base: - self.__base = maximum_base - self.__mask = ~-(1 << self.__base) - - print([self.__mask, self.__base, self.__alphabet]) - - def to_string(self:Self, code:str|int|Sequence[int]) -> str: - if isinstance(code, str): - return code - if isinstance(code, (list, tuple)): - return "".join([self.__alphabet[hexa] for hexa in code]) - if isinstance(code, int): - - string:str = "" - - while code: - string = self.__alphabet[code & self.__mask] + string - code >>= self.__base - - return string - return "" - - def to_integer(self:Self, code:str|int|Sequence[int]) -> int: - if isinstance(code, str): - - integer:int = 0 - hexa:str - - for i, hexa in enumerate(reversed(code)): - integer |= self.__alphabet_map[hexa] << self.__base * i - - return integer - if isinstance(code, (list, tuple)): - - integer:int = 0 - hexa:int - - for i, hexa in enumerate(reversed(code)): - integer |= hexa << self.__base * i - - return integer - if isinstance(code, int): - return code - return 0 - - def to_array(self:Self, code:str|int|Sequence[int]) -> list[int]: - if isinstance(code, str): - return [self.__alphabet_map[hexa] for hexa in code] - if isinstance(code, list): - return list(code) - if isinstance(code, tuple): - return code - if isinstance(code, int): - - array:list[int] = [] - - while code: - array.append(code & self.__mask) - code >>= self.__base - - return list(reversed(array)) - return [] - - def reset_bak(self:Self, code:int, start:int, length:int) -> int: - return code and (code & ~(~-(1 << length) << start)) - - def set_bak(self:Self, code:int, map:Sequence[int], codes:Sequence[int], start:int = 0, clean_bits:int = 0) -> int: - - new_code:int = 0 - shift:int = 0 - block:int - i:int - - code = self.reset(code, start, clean_bits) - - for i, block in enumerate(map): - new_code |= (codes[i] or (code >> start + shift & ~-(1 << block))) << shift - shift += block - - return ( - (code & ~-(1 << start)) | - (new_code << start) | - (code & ~(~-(1 << start + shift))) - ) - - def has(self:Self, code:str) -> bool: - - errors:tuple[str] = self.__alphabet[1:] - character:str - - for character in code: - if character in errors: - return True - return False - - def clean(self:Self, code:str) -> str: - - while code[0] == self.__alphabet[0]: - code = code[1:] - - return code - - def reset(self:Self, code:str, start:int = 0, length:int = 0) -> str: - - i:int - character:str - total:int = start + (length or (length := len(code) * self.__base)) - _from:int|None = -start // self.__base or None - _to:int|None = (-total // self.__base) - (1 if total % self.__base else 0) or None - hexas:list[int] = [] - - if _from: - start += _from * self.__base - total += _from * self.__base - - for i, character in enumerate(reversed(code[-_to:_from])): - - bit:int = i * self.__base - next_bit:int = bit + self.__base - - if bit >= start and next_bit < total: - hexas.append(0) - continue - - hexa:int = self.__alphabet_map[character] - j:int - - for j in range(self.__base): - if bit < start: - continue - if bit >= total: - break - hexa &= ~(1 << j) - bit += 1 - - return ( - (code[:_to] if _to else "") + - "".join(self.__alphabet[hexa] for hexa in hexas)[::-1] + - (code[_from:] if _from else "") - ) - - def set(self:Self, code:str, new_code:int|str, start:int = 0, clean_bits:int = 0) -> str: - - - - return code - - def validate(self:Self, - code:int, - map:Sequence[int], - messages:Sequence[Sequence[str]] = [] - ) -> tuple[tuple[int, str]]: - - errors:list[tuple[int, str]] = [] - - if code: - - shift:int = 0 - l:int = len(messages) - i:int - block:int - - for i, block in enumerate(map): - - subcode:int = (code >> shift) & ~-(1 << block) - - shift += block - subcode and errors.append((i, ( - messages[i][subcode - 1] if i < l and subcode - 1 < len(messages[i]) else - "error_" + str(i) + "_" + str(subcode)))) - - return len(errors) != 0, tuple(errors) - - @classmethod - def get_keys(cls:type[Self], *items:Sequence[Any|None]) -> list[str]: - - keys:list[str] = [] - item:Any|None - - for item in items: - if isinstance(item, str): - cls.RE_KEY.match(item) and keys.append(item) - elif isinstance(item, (list, tuple)): - keys.extend(cls.get_keys(*item)) - - return keys - - @classmethod - def get_dictionaries(cls:type[Self], *items:Sequence[Any|None]) -> list[dict[str, Any|None]]: - - dictionaries:list[str] = [] - item: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_value(cls:type[Self], - keys:str|Sequence[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|Sequence[Any|None]) -> str|Sequence[Any|None]: - if isinstance(items, str): - return "".join(character for i, character in enumerate(items) if items.index(character) == i) - if isinstance(items, tuple): - return tuple(item for i, item in enumerate(items) if items.index(item) == i) - if isinstance(items, list): - return [item for i, item in enumerate(items) if items.index(item) == i] - return items \ No newline at end of file diff --git a/Python/v2/tests.py b/Python/v2/tests.py deleted file mode 100644 index 2e1579a..0000000 --- a/Python/v2/tests.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from ErrorsManager import ErrorsManager - -class Tests: - - @staticmethod - def builder() -> None: - print(ErrorsManager()) - - @staticmethod - def conversions() -> None: - - option:str|int|list[int] - errors:ErrorsManager = ErrorsManager() - - for option in ( - "Hola", 923452, [45, 2, 0, 12] - ): - - string:str = errors.to_string(option) - integer:int = errors.to_integer(option) - array:list[int] = errors.to_array(option) - - print(option) - print(["T", { - "s" : string, - "i" : integer, - "a" : array - }]) - print(["S", { - "s" : errors.to_string(string), - "i" : errors.to_integer(string), - "a" : errors.to_array(string) - }]) - print(["I", { - "s" : errors.to_string(integer), - "i" : errors.to_integer(integer), - "a" : errors.to_array(integer) - }]) - print(["A", { - "s" : errors.to_string(array), - "i" : errors.to_integer(array), - "a" : errors.to_array(array) - }]) - -Tests.conversions() \ No newline at end of file diff --git a/SQLServer/ErrorsManager.server.sql b/SQLServer/ErrorsManager.server.sql new file mode 100644 index 0000000..4e36d4c --- /dev/null +++ b/SQLServer/ErrorsManager.server.sql @@ -0,0 +1,621 @@ +if (select top 1 0 from sys.databases where name = 'ErrorsManager') is null create database ErrorsManager collate Latin1_General_CI_AS +go +use ErrorsManager + +if object_id(N'dbo.tables_drop', N'P') is not null drop procedure dbo.tables_drop +go +create procedure dbo.tables_drop as begin set nocount on + + -- Level 1. + if object_id(N'dbo.Settings', N'U') is not null drop table dbo.Settings + + -- Level 0. + if object_id(N'dbo.Sets', N'U') is not null drop table dbo.Sets + if object_id(N'dbo.Types', N'U') is not null drop table dbo.Types + if object_id(N'dbo.Messages', N'U') is not null drop table dbo.Messages + +end +go + +if object_id(N'dbo.tables_create', N'P') is not null drop procedure dbo.tables_create +go +create procedure dbo.tables_create as begin set nocount on + + -- Level 0. + if object_id(N'dbo.Sets', N'U') is null create table dbo.Sets( + id int not null identity(1, 1), + [key] varchar(32) not null, + alphabet varchar(128) collate Latin1_General_CS_AS not null, + base smallint not null, + power tinyint not null, + in_use bit not null constraint sets_df_in_use default 0, + [description] varchar(512), + date_in datetime not null constraint sets_df_date_in default getdate(), + last_selection datetime, + date_out datetime, + constraint sets_pk primary key clustered (id), + constraint sets_uk_key unique nonclustered ([key]) with (fillfactor = 90), + constraint sets_uk_data unique nonclustered (alphabet, base, power) with (fillfactor = 90), + constraint sets_ck_key check ( + [key] not like '%[^a-zA-Z0-9_]%' and + len([key]) > 0 and + len([key]) <= 32 + ), + constraint sets_ck_alphabet check ( + datalength(alphabet) >= 2 and + datalength(alphabet) <= 128 + ), + constraint sets_ck_base check (base >= 2 and base <= 128), + constraint sets_ck_power check (power > 0 and power < 8) + ) + + if object_id(N'dbo.Types', N'U') is null create table dbo.Types( + id int not null identity(1, 1), + [name] varchar(32) not null, + [description] varchar(512), + date_in datetime not null constraint types_df_date_in default getdate(), + date_out datetime, + constraint types_pk primary key clustered (id), + constraint types_uk_name unique nonclustered ([name]) with (fillfactor = 90), + constraint types_ck_name check ( + [name] not like '%[^a-zA-Z0-9_]%' and + len([name]) > 0 and + len([name]) <= 32 + ) + ) + + if object_id(N'dbo.Messages', N'U') is null create table dbo.Messages( + id int not null identity(1, 1), + [bit] smallint not null, + [message] varchar(64) not null, + date_in datetime not null constraint messages_df_date_in default getdate(), + date_out datetime, + constraint messages_pk primary key clustered (id), + constraint messages_uk_data unique nonclustered ([bit], [message]) with (fillfactor = 90) + ) + + -- Level 1. + if object_id(N'dbo.Settings', N'U') is null create table dbo.Settings( + id int not null identity(1, 1), + [type] integer not null, + [key] varchar(32) not null, + [value] varchar(128), + [description] varchar(512), + date_in datetime not null constraint settings_df_date_in default getdate(), + date_out datetime, + constraint settings_pk primary key clustered (id), + constraint settings_fk_type foreign key ([type]) references dbo.Types(id) + on update no action + on delete no action, + constraint settings_uk_key unique nonclustered ([key]) with (fillfactor = 90), + constraint settings_ck_key check ( + [key] not like '%[^a-zA-Z0-9_]%' and + len([key]) > 0 and + len([key]) <= 32 + ) + ) + +end +go + +if object_id(N'dbo.tables_update', N'P') is not null drop procedure dbo.tables_update +go +create procedure dbo.tables_update as begin set nocount on + + declare @database varchar(64) = db_name() + + -- Level 0. + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Sets' and column_name = 'key') is null + alter table dbo.Sets add + [key] varchar(32) not null, + constraint sets_uk_key unique nonclustered ([key]) with (fillfactor = 90), + constraint sets_ck_key check ( + [key] not like '%[^a-zA-Z0-9_]%' and + len([key]) > 0 and + len([key]) <= 32 + ) + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Sets' and column_name = 'alphabet') is null + alter table dbo.Sets add + alphabet varchar(128) not null, + constraint sets_ck_alphabet check ( + datalength(alphabet) >= 2 and + datalength(alphabet) <= 128 + ) + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Sets' and column_name = 'base') is null + alter table dbo.Sets add + base smallint not null, + constraint sets_ck_base check (base >= 2 and base <= 128) + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Sets' and column_name = 'power') is null + alter table dbo.Sets add + power tinyint not null, + constraint sets_ck_power check (power > 0 and power < 8) + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Sets' and column_name = 'in_use') is null + alter table dbo.Sets add in_use bit not null constraint sets_df_in_use default 0 + if (select top 1 0 from information_schema.constraints where table_catalog = @database and table_name = 'Sets' and constraint_name = 'sets_uk_data') is null + alter table dbo.Sets add constraint sets_uk_data unique nonclustered (alphabet, base, power) with (fillfactor = 90) + + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Types' and column_name = 'name') is null + alter table dbo.Types add + [name] varchar(32) not null, + constraint types_uk_name unique nonclustered ([name]) with (fillfactor = 90), + constraint types_ck_name check ( + [name] not like '%[^a-zA-Z0-9_]%' and + len([name]) > 0 and + len([name]) <= 32 + ) + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Types' and column_name = 'description') is null + alter table dbo.Types add [description] varchar(512) + + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Messages' and column_name = 'bit') is null + alter table dbo.Messages add [bit] smallint not null + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Messages' and column_name = 'message') is null + alter table dbo.Messages add [message] varchar(64) not null + if (select top 1 0 from information_schema.constraints where table_catalog = @database and table_name = 'Messages' and constraint_name = 'messages_uk_data') is null + alter table dbo.Messages add constraint messages_uk_data unique nonclustered ([bit], [message]) with (fillfactor = 90) + + -- Level 1. + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Settings' and column_name = 'key') is null + alter table dbo.Settings add + [key] varchar(32) not null, + constraint settings_uk_key unique nonclustered ([key]) with (fillfactor = 90), + constraint settings_ck_key check ( + [key] not like '%[^a-zA-Z0-9_]%' and + len([key]) > 0 and + len([key]) <= 32 + ) + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Settings' and column_name = 'value') is null + alter table dbo.Settings add [value] varchar(128) + if (select top 1 0 from information_schema.columns where table_catalog = @database and table_name = 'Settings' and column_name = 'description') is null + alter table dbo.Settings add [description] varchar(512) + +end +go + +if object_id(N'dbo.tables_fill', N'P') is not null drop procedure dbo.tables_fill +go +create procedure dbo.tables_fill as begin set nocount on + + if object_id(N'tempdb..#Settings', N'U') is not null drop table #Settings + create table #Settings( + [type] varchar(32) not null, + [key] varchar(32) not null, + [value] varchar(128) + ) + if object_id(N'tempdb..#Messages', N'U') is not null drop table #Messages + create table #Messages( + [bit] smallint not null, + [message] varchar(64) not null + ) + + insert into #Settings([type], [key], [value]) values + ('string', 'alphabet', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='), + ('integer', 'base', '64') + + insert into #Messages([bit], [message]) values + (0, 'invalid_alphabet'), + (1, 'invalid_base'), + (2, 'invalid_alphabet_type'), + (3, 'too_short_alphabet'), + (4, 'repeated_characters_in_alphabet'), + (5, 'too_long_alphabet'), + (6, 'base_lower_than_2'), + (7, 'base_greater_than_128'), + (8, 'base_greater_than_alphabet') + + insert into dbo.Types([name]) select distinct [type] from #Settings where [type] not in ( + select [name] from dbo.Types + ) + insert into dbo.Settings([type], [key], [value]) select + types.id, + settings.[key], + settings.[value] + from #Settings as settings + inner join dbo.Types as types on types.name = settings.type + where settings.[key] not in ( + select [key] from dbo.Settings + ) + + insert into dbo.Messages([bit], [message]) select + [bit], + [message] + from #Messages where ([bit], [message]) not in ( + select [bit], [message] from dbo.Messages + ) + + if (select count(1) from dbo.Sets) = 0 begin + end + + drop table #Settings + +end +go + +if object_id(N'dbo.settings_get', N'FN') is not null drop function dbo.settings_get +go +create function dbo.settings_get( + @key varchar(32), + @default varchar(128) +) returns varchar(128) as begin + return isnull(( + select top 1 [value] from dbo.Settings where [key] = @key and date_out is null order by date_in desc + ), @default) +end +go + +if object_id(N'dbo.settings_get_int', N'FN') is not null drop function dbo.settings_get_int +go +create function dbo.settings_get_int( + @key varchar(32), + @default integer +) returns integer as begin + return convert(integer, dbo.settings_get(@key, @default)) +end +go + +if object_id(N'dbo.shift', N'FN') is not null drop function dbo.shift +go +create function dbo.shift( + @value integer, + @bits smallint +) returns integer as begin + return (case + when @bits is null or @value is null then 0 + when @bits > 0 then @value * power(2, @bits) + when @bits < 0 then @value / power(2, -@bits) + else @value end) +end +go + +if object_id(N'dbo.unique', N'FN') is not null drop function dbo.unique +go +create function dbo.unique( + @string varchar(max) +) returns varchar(128) as begin + + declare @i integer = 1 + declare @l integer = datalength(@string) + declare @unique varchar(128) = '' + + while @i <= @l begin + + declare @character char(1) = substring(@string, @i, 1) + + if charindex(@character, @unique) = 0 + set @unique += @character + set @i += 1 + + end + + return @unique +end +go + +if object_id(N'dbo.log2', N'FN') is not null drop function dbo.log2 +go +create function dbo.log2( + @value float +) returns float as begin + return log(@value) / log(2) +end +go + +if object_id(N'dbo.set_alphabet', N'P') is not null drop procedure dbo.set_alphabet +go +create procedure dbo.set_alphabet( + @alphabet varchar(max), + @base smallint, + @id integer output, + @error integer output +) begin set nocount on + + declare @original_length integer + declare @power tinyint + + set @error = 0 + + if @alphabet is null set @alphabet = dbo.settings_get('alphabet', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=') + if @base is null set @base = dbo.settings_get_int('base', 64) + + set @original_length = datalength(@alphabet) + + set @alphabet = dbo.unique(@alphabet) + + if datalength(@alphabet) > 2 begin + set @error = @error | dbo.shift(1, 3) + set @alphabet = dbo.settings_get('alphabet', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=') + end + if datalength(@alphabet) != original_length + set @error = @error | dbo.shift(1, 4) + if datalength(@alphabet) > 128 + set @error = @error | dbo.shift(1, 5) + + set @error = @error | dbo.shift(1, case + when @base < 2 then 6 + when @base > 128 then 7 + when @base >= datalength(@alphabet) then 8 + else null end) + + if dbo.shift(error, -6) = 0 set @alphabet = substring(@alphabet, 1, @base) + + set @power = cast(dbo.log2(datalength(substring(@alphabet, 1, 128))) as integer) + set @base = power(2, @power) + + insert into dbo.Sets(alphabet, base, power) values + (substring(@alphabet, 1, @base), @base, @power) + set @id = scope_identity() + +end +go + +if object_id(N'dbo.change', N'P') is not null drop procedure dbo.change +go +create procedure dbo.change( + @key varchar(32) +) begin set nocount on + if (select top 1 0 from dbo.Sets where [key] = @key and in_use = 1) = 0 begin + update dbo.Sets set in_use = 0 where in_use = 1 + update dbo.Sets set + in_use = 1, + last_selection = getdate() + where [key] = @key + end +end + +if object_id(N'dbo.get_alphabet', N'FN') is not null drop function dbo.get_alphabet +go +create function dbo.get_alphabet() returns varchar(128) as begin + return (select top 1 alphabet from dbo.Sets where in_use = 1) +end +go + +if object_id(N'dbo.to_string', N'FN') is not null drop function dbo.to_string +go +create function dbo.to_string( + @code integer +) returns varchar(512) as begin + + declare @hexas varchar(512) = '' + declare @alphabet varchar(128) + declare @base smallint + + select top 1 @alphabet = alphabet, @base = base from dbo.Sets where in_use = 1 + + while @code != 0 begin + + declare @module integer = @code % @base + + set @hexas = @hexas + substring(@alphabet, @module + 1, 1) + set @code = @code / @base + + end + + return @hexas +end +go + +if object_id(N'dbo.to_integer', N'FN') is not null drop function dbo.to_integer +go +create function dbo.to_integer( + @code varchar(512) +) returns integer as begin + + declare @integer integer = 0 + declare @alphabet varchar(128) + declare @base smallint + declare @i integer = datalength(@code) + + select top 1 @alphabet = alphabet, @base = base from dbo.Sets where in_use = 1 + + while @i > 0 begin + + declare @value integer = charindex(substring(@code, @i, 1), @alphabet) + + if @value != 0 set @integer = @integer * @base + @value - 1 + set @i = @i - 1 + + end + + return @integer +end +go + +if object_id(N'dbo.to_binary', N'FN') is not null drop function dbo.to_binary +go +create function dbo.to_binary( + @integer integer +) returns varchar(32) as begin + + declare @binary varchar(32) = '' + + while @integer != 0 begin + set @binary = convert(char(1), @integer % 2) + @binary + set @integer = @integer / 2 + end + + return @binary +end +go + +if object_id(N'dbo.to_string_binary', N'FN') is not null drop function dbo.to_string_binary +go +create function dbo.to_string_binary( + @string varchar(512), + @integer integer +) returns varchar(3584) as begin + + declare @binary varchar(3584) = '' + declare @alphabet varchar(128) + declare @base smallint + declare @power tinyint + + select top 1 @alphabet = alphabet, @base = base, @power = power from dbo.Sets where in_use = 1 + + if @string is not null begin + + declare @i integer = datalength(@string) + + while @i > 0 begin + + declare @value integer = charindex(substring(@string, @i, 1), @alphabet) + + if @value != 0 set @binary = right('0000000' + dbo.to_binary(@value - 1), @power) + @binary + set @i = @i - 1 + + end + + end else if @integer is not null begin + set @binary = dbo.to_binary(@integer) + while len(@binary) % @power != 0 + set @binary = '0' + @binary + end + + return @binary +end +go + +if object_id(N'dbo.get_bits', N'FN') is not null drop function dbo.get_bits +go +create function dbo.get_bits( + @string varchar(512), + @integer integer +) returns smallint as begin + if @string is not null begin + + declare @alphabet varchar(128) + declare @base smallint + declare @power tinyint + + select top 1 @alphabet = alphabet, @base = base, @power = power from dbo.Sets where in_use = 1 + + return (case + when datalength(@string) = 0 then 0 + else (datalength(@string) - 1) * @power + ceiling(dbo.log2(charindex(substring(@string, datalength(@string), 1), @alphabet))) end) + end + if @integer is not null + return ceiling(dbo.log2(@integer)) + return 0 +end +go + +if object_id(N'dbo.get_from_bits', N'P') is not null drop procedure dbo.get_from_bits +go +create procedure dbo.get_from_bits( + @string varchar(512), + @integer integer, + @from smallint output, + @bits smallint output +) begin set nocount on + if @from < 0 begin + set @from = dbo.get_bits(@string, @integer) + @from + if @from < 0 set @from = 0 + end + if @bits < 0 begin + set @from = @from + @bits + set @bits = -@bits + if @from < 0 begin + set @bits = @bits + @from + set @from = 0 + end + end +end +go + +if object_id(N'dbo.clean', N'P') is not null drop procedure dbo.clean +go +create procedure dbo.clean( + @string varchar(512) output, + @integer integer output +) as begin set nocount on + if @string is not null begin + + declare @character_0 char(1) + + select top 1 @character_0 = substring(alphabet, 1, 1) from dbo.Sets where in_use = 1 + + while datalength(@string) != 0 and right(@string, 1) = @character_0 + set @string = left(@string, datalength(@string) - 1) + if @string = '' set @string = @character_0 + + end +end +go + +if object_id(N'dbo.get_range', N'P') is not null drop procedure dbo.get_range +go +create procedure dbo.get_range( + @string varchar(512) output, + @integer integer output, + @from smallint, + @bits smallint +) begin set nocount on + if @string is not null begin + + execute dbo.get_from_bits @string, @integer, @from output, @bits output + + if bits = 0 set bits = dbo.get_bits(@string, @integer) - @from + if bits > 0 begin + + declare @alphabet varchar(128) + declare @base smallint + declare @power tinyint + + select top 1 @alphabet = alphabet, @base = base, @power = power from dbo.Sets where in_use = 1 + + if @from > 0 begin + + declare shift smallint = @from % @power + declare mask smallint = ~-@base + + set @string = substring(@string, @from / @power + 1, datalength(@string)) + if @shift != 0 and datalength(@string) > 0 begin + + declare l integer = datalength(@string) + declare i integer = 1 + + while i < l begin + set @string = ( + left(@string, i - 1) + + substring(@alphabet, (( + dbo.shift(charindex(@alphabet, substring(@string, i, 1)), @shift) | + dbo.shift(charindex(@alphabet, substring(@string, i + 1, 1)), @power - @shift) + ) & @mask) + 1, 1) + + right(@string, l - i) + ) + set i = i + 1 + end + + end + + end + if @bits > 0 begin + + declare @shift smallint = @bits % @power + + set @string = left(@string, ceiling((@from + @bits) / @power)) + if @shift != 0 and datalength(@string) > 0 begin + set @string = ( + substring(@string, 1, datalength(@string) - 1) + + substring(@alphabet, ( + dbo.shift(charindex(@alphabet, right(@string, 1)), -@shift) & ~-power(2, @power - @shift) + ) + 1, 1) + ) + + end + + end + + execute dbo.clean @string output, @integer output + + end else if @integer is not null begin + + 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 @from + @bits > 31 set @bits = 31 - @from + set @integer = @integer & (dbo.shift(1, @bits) - 1) + end + + end +end +go \ No newline at end of file diff --git a/VB/ErrorsManager.vb b/VB/ErrorsManager.vb index 2d05ba4..5e7c425 100644 --- a/VB/ErrorsManager.vb +++ b/VB/ErrorsManager.vb @@ -270,7 +270,8 @@ Namespace ErrorsManager End If - ElseIf bits > 0 Then + End If + If bits > 0 Then Dim shift As Byte = CByte(bits Mod power) @@ -375,7 +376,7 @@ Namespace ErrorsManager 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) And mask) Or (hexas(i - 1) >> (power - shift))) + hexas(i) = CByte(((hexas(i) << shift) Or (hexas(i - 1) >> (power - shift))) And mask) Next hexas(0) = CByte((hexas(0) << shift) And mask) @@ -427,7 +428,7 @@ Namespace ErrorsManager Next If hexa_from = hexa_to Then - hexas(hexa_to) = CByte(hexas(hexa_to) And (from_mask And to_mask)) + 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) diff --git a/VB/Tests.vb b/VB/Tests.vb index 1f8e524..d387e9b 100644 --- a/VB/Tests.vb +++ b/VB/Tests.vb @@ -98,7 +98,7 @@ Namespace ErrorsManager Dim [error] As New FullError(errors, seed.Next(0, 1 << seed.Next(0, 16))) Dim shifted As New FullError(errors, 0) Dim unshifted As New FullError(errors, 0) - Dim bitwise As Integer = 10 - seed.Next(0, 20) + Dim bitwise As Integer = seed.Next(-10, 10) Console.WriteLine($"BITWISE: {bitwise}") @@ -283,7 +283,7 @@ Namespace ErrorsManager set_string.array = errors.set([error].array, value._string, [from], bits) set_array.array = errors.set([error].array, value.array, [from], bits) - Console.WriteLine($"SET: from {[from]} bits {bits} to {value}") + Console.WriteLine($"SET: from {[from]} bits {bits} to [{value._string}, {FullError.print(value.array)}, {value._integer}]") Console.WriteLine($"ERROR: {errors.to_string_binary([error]._integer)} - VALUE: {errors.to_string_binary(value._integer)}") Console.WriteLine($"INTEGER: {errors.to_string_binary(set_integer._integer)} - {errors.to_string_binary(set_integer._string)} - {errors.to_string_binary(set_integer.array)}") Console.WriteLine($"STRING: {errors.to_string_binary(set_string._integer)} - {errors.to_string_binary(set_string._string)} - {errors.to_string_binary(set_string.array)}") diff --git a/version b/version index 72f9fa8..28af839 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.2.4 \ No newline at end of file +0.2.5 \ No newline at end of file