From 26d9650b0e09ccf0c9d8bf99f0f040ea148d2038 Mon Sep 17 00:00:00 2001 From: Mattias Wadman Date: Thu, 10 Feb 2022 00:38:40 +0100 Subject: [PATCH] interp: Refactor radix* into toradix($base)/fromradix($base) There is also toradix($base; $table)/fromradix($base; $table) for custom symbols and bases. Add radix tests Part of cleaning up all convert/tranformation functions into to/from*. Remove number_to_bytes as with better binary support it can be written as: 1234 | tobytes | [.[range(.size)]] and soon as 1234 | tobytes | explode --- dev/snippets.jq | 3 +- pkg/interp/funcs.jq | 113 ++++++++++--------------------- pkg/interp/funcs_test.jq | 29 -------- pkg/interp/testdata/funcs.fqtest | 21 ++++++ 4 files changed, 58 insertions(+), 108 deletions(-) diff --git a/dev/snippets.jq b/dev/snippets.jq index b49995d8..6ec411be 100644 --- a/dev/snippets.jq +++ b/dev/snippets.jq @@ -41,7 +41,8 @@ def urldecode: # ex: .frames | changes(.header.sample_rate) def changes(f): streaks_by(f)[].[0]; -def radix62sp: radix(62; "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; { +def toradix62sp: toradix(62; "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); +def fromradix62sp: fromradix(62; { "0": 0, "1": 1, "2": 2, "3": 3,"4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "a": 10, "b": 11, "c": 12, "d": 13, "e": 14, "f": 15, "g": 16, "h": 17, "i": 18, "j": 19, "k": 20, "l": 21, "m": 22, "n": 23, diff --git a/pkg/interp/funcs.jq b/pkg/interp/funcs.jq index 655ec5bb..0ea830ef 100644 --- a/pkg/interp/funcs.jq +++ b/pkg/interp/funcs.jq @@ -202,22 +202,9 @@ def table(colmap; render): ) end; -# convert number to array of bytes -def number_to_bytes($bits): - def _number_to_bytes($d): - if . > 0 then - . % $d, (intdiv(.; $d) | _number_to_bytes($d)) - else - empty - end; - if . == 0 then [0] - else [_number_to_bytes(pow(2; $bits) | _to_int)] | reverse - end; -def number_to_bytes: - number_to_bytes(8); - -def from_radix($base; $table): - ( split("") +def fromradix($base; $table): + ( if type != "string" then error("cannot fromradix convert: \(.)") end + | split("") | reverse | map($table[.]) | if . == null then error("invalid char \(.)") end @@ -229,75 +216,45 @@ def from_radix($base; $table): ) | .[1] ); - -def to_radix($base; $table): - if . == 0 then "0" - else - ( [ recurse(if . > 0 then intdiv(.; $base) else empty end) | . % $base] - | reverse - | .[1:] - | if $base <= ($table | length) then - map($table[.]) | join("") - else - error("base too large") - end - ) - end; - -def radix($base; $to_table; $from_table): - if . | type == "number" then to_radix($base; $to_table) - elif . | type == "string" then from_radix($base; $from_table) - else error("needs to be number or string") - end; - -def radix2: radix(2; "01"; {"0": 0, "1": 1}); -def radix8: radix(8; "01234567"; {"0": 0, "1": 1, "2": 2, "3": 3,"4": 4, "5": 5, "6": 6, "7": 7}); -def radix16: radix(16; "0123456789abcdef"; { +def fromradix($base): + fromradix($base; { "0": 0, "1": 1, "2": 2, "3": 3,"4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, - "a": 10, "b": 11, "c": 12, "d": 13, "e": 14, "f": 15 - }); -def radix62: radix(62; "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; { - "0": 0, "1": 1, "2": 2, "3": 3,"4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, - "A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15, "G": 16, - "H": 17, "I": 18, "J": 19, "K": 20, "L": 21, "M": 22, "N": 23, - "O": 24, "P": 25, "Q": 26, "R": 27, "S": 28, "T": 29, "U": 30, - "V": 31, "W": 32, "X": 33, "Y": 34, "Z": 35, - "a": 36, "b": 37, "c": 38, "d": 39, "e": 40, "f": 41, "g": 42, - "h": 43, "i": 44, "j": 45, "k": 46, "l": 47, "m": 48, "n": 49, - "o": 50, "p": 51, "q": 52, "r": 53, "s": 54, "t": 55, "u": 56, - "v": 57, "w": 58, "x": 59, "y": 60, "z": 61 - }); -def radix62: radix(62; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; { - "A": 0, "B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, - "H": 7, "I": 8, "J": 9, "K": 10, "L": 11, "M": 12, "N": 13, - "O": 14, "P": 15, "Q": 16, "R": 17, "S": 18, "T": 19, "U": 20, - "V": 21, "W": 22, "X": 23, "Y": 24, "Z": 25, - "a": 26, "b": 27, "c": 28, "d": 29, "e": 30, "f": 31, "g": 32, - "h": 33, "i": 34, "j": 35, "k": 36, "l": 37, "m": 38, "n": 39, - "o": 40, "p": 41, "q": 42, "r": 43, "s": 44, "t": 45, "u": 46, - "v": 47, "w": 48, "x": 49, "y": 50, "z": 51, - "0": 52, "1": 53, "2": 54, "3": 55, "4": 56, "5": 57, "6": 58, "7": 59, "8": 60, "9": 61 - }); -def radix64: radix(64; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; { - "A": 0, "B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, - "H": 7, "I": 8, "J": 9, "K": 10, "L": 11, "M": 12, "N": 13, - "O": 14, "P": 15, "Q": 16, "R": 17, "S": 18, "T": 19, "U": 20, - "V": 21, "W": 22, "X": 23, "Y": 24, "Z": 25, - "a": 26, "b": 27, "c": 28, "d": 29, "e": 30, "f": 31, "g": 32, - "h": 33, "i": 34, "j": 35, "k": 36, "l": 37, "m": 38, "n": 39, - "o": 40, "p": 41, "q": 42, "r": 43, "s": 44, "t": 45, "u": 46, - "v": 47, "w": 48, "x": 49, "y": 50, "z": 51, - "0": 52, "1": 53, "2": 54, "3": 55, "4": 56, "5": 57, "6": 58, "7": 59, "8": 60, "9": 61, - "+": 62, "/": 63 + "a": 10, "b": 11, "c": 12, "d": 13, "e": 14, "f": 15, "g": 16, + "h": 17, "i": 18, "j": 19, "k": 20, "l": 21, "m": 22, "n": 23, + "o": 24, "p": 25, "q": 26, "r": 27, "s": 28, "t": 29, "u": 30, + "v": 31, "w": 32, "x": 33, "y": 34, "z": 35, + "A": 36, "B": 37, "C": 38, "D": 39, "E": 40, "F": 41, "G": 42, + "H": 43, "I": 44, "J": 45, "K": 46, "L": 47, "M": 48, "N": 49, + "O": 50, "P": 51, "Q": 52, "R": 53, "S": 54, "T": 55, "U": 56, + "V": 57, "W": 58, "X": 59, "Y": 60, "Z": 61, + "@": 62, "_": 63, }); +def toradix($base; $table): + ( if type != "number" then error("cannot toradix convert: \(.)") end + | if . == 0 then "0" + else + ( [ recurse(if . > 0 then intdiv(.; $base) else empty end) | . % $base] + | reverse + | .[1:] + | if $base <= ($table | length) then + map($table[.]) | join("") + else + error("base too large") + end + ) + end + ); +def toradix($base): + toradix($base; "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_"); + # TODO: rename keys and add more, ascii/utf8/utf16/codepoint name?, le/be, signed/unsigned? def iprint: { - bin: "0b\(radix2)", - oct: "0o\(radix8)", + bin: "0b\(toradix(2))", + oct: "0o\(toradix(8))", dec: "\(.)", - hex: "0x\(radix16)", + hex: "0x\(toradix(16))", str: (try ([.] | implode) catch null), }; diff --git a/pkg/interp/funcs_test.jq b/pkg/interp/funcs_test.jq index ee651e03..cc39fc31 100644 --- a/pkg/interp/funcs_test.jq +++ b/pkg/interp/funcs_test.jq @@ -45,33 +45,4 @@ include "funcs"; ["1234", 2, ["12","34"]], ["1234", 3, ["123","4"]] ][] | . as $t | assert("\($t[0]) | chunk(\($t[1]))"; $t[2]; $t[0] | chunk($t[1]))) -, - ([ - # 0xfffffffffffffffffffffffffffffffffffffffffffff - [1532495540865888858358347027150309183618739122183602175, 8, [ - 15, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255 - ]] - ][] | . as $t | assert("\($t[0]) | number_to_bytes(\($t[1]))"; $t[2]; $t[0] | number_to_bytes($t[1]))) ) diff --git a/pkg/interp/testdata/funcs.fqtest b/pkg/interp/testdata/funcs.fqtest index bb36b277..3f8928a5 100644 --- a/pkg/interp/testdata/funcs.fqtest +++ b/pkg/interp/testdata/funcs.fqtest @@ -5,4 +5,25 @@ null> "abc" | topem | "before" + . + "between" + . + "after" | frompem | tostrin "abc" "abc" null> +null> (0,1,1024,99999999999999999999) as $n | (2,8,16,62,64) as $r | "\($r): \($n) \($n | toradix($r)) \($n | toradix($r) | fromradix($r))" | println +2: 0 0 0 +8: 0 0 0 +16: 0 0 0 +62: 0 0 0 +64: 0 0 0 +2: 1 1 1 +8: 1 1 1 +16: 1 1 1 +62: 1 1 1 +64: 1 1 1 +2: 1024 10000000000 1024 +8: 1024 2000 1024 +16: 1024 400 1024 +62: 1024 gw 1024 +64: 1024 g0 1024 +2: 99999999999999999999 1010110101111000111010111100010110101100011000011111111111111111111 99999999999999999999 +8: 99999999999999999999 12657072742654303777777 99999999999999999999 +16: 99999999999999999999 56bc75e2d630fffff 99999999999999999999 +62: 99999999999999999999 1V973MbJYWoT 99999999999999999999 +64: 99999999999999999999 1mL7nyRz3___ 99999999999999999999 null> ^D