Last active
July 31, 2020 07:17
-
-
Save nikcorg/0490739e92f942c34c8a3d12cf95c694 to your computer and use it in GitHub Desktop.
GSM 7 Bit Decoder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This decoder is based on this answer https://stackoverflow.com/a/21115816 | |
// It's not perfect, e.g. it does not accommodate the extended alphabet. | |
// | |
// Solution from SO answer paraphrased below: | |
// | |
// For input: C7F7FBCC2E03 | |
// 1) Form tuples for hex numbers and reverse | |
// -> 03-2E-CC-FB-F7-C7 | |
// 2) Convert hex to 8-bit binary octets | |
// -> 00000011-00101110-11001100-11111011-11110111-11000111 | |
// 3) Make 7-bit binary septets | |
// -> 000000-1100101-1101100-1100111-1101111-1101111-1000111 | |
// 4) Discard the first septet | |
// 5) Convert remaining binary septets to decimal | |
// 6) Map decimals to ASCII characters (doesn't work for extended alphabet) | |
// 1000111- 71-G | |
// 1101111-111-o | |
// 1101111-111-o | |
// 1100111-103-g | |
// 1101100-108-l | |
// 1100101-101-e | |
function fromGsm7Bit(s) { | |
// Split the string to tuples, reverse and join for hex numbers | |
const hex = aperture(2, s.replace(/\s+/g, "").split("")) | |
.reverse() | |
.map(xs => xs.join("")); | |
// Parse the hex numbers to base 10 | |
const dec = hex.map(s => parseInt(s, 16)); | |
// Map the base 10 numbers to base 2 numbers padded to 8 bits | |
const bin = dec.map(n => n.toString(2)).map(s => s.padStart(8, 0)); | |
// Split the binary string to 7 bit septets, | |
// starting from the right side, which is | |
// the reason for all the reversing. | |
const bin7 = aperture( | |
7, | |
bin | |
.join("") | |
.split("") | |
.reverse() | |
).map(xs => xs.reverse().join("")); | |
return bin7 | |
.map(bin => parseInt(bin, 2)) // Again to decimal | |
.filter(dec => dec > 0) // Omit null chars | |
.map(dec => String.fromCharCode(dec)) // Then finally to characters | |
.join(""); | |
} | |
function aperture(len, xs) { | |
const ys = xs.slice(0, len); | |
const zs = xs.slice(len); | |
if (ys.length === 0) { | |
return ys; | |
} else if (ys.length < len) { | |
return [ys]; | |
} | |
return [ys].concat(aperture(len, zs)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ref: https://mobile.twitter.com/krp_poliisi/status/1072057880386437121