Created
May 10, 2020 06:13
-
-
Save gnachman/cd82b2c4d47970f4e62ff7d56feae86a to your computer and use it in GitHub Desktop.
Prototype of pure POSIX terminal features decoder
This file contains 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
#!/bin/dash | |
__tf_decode() { | |
local TABLE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" | |
local COUNT=0 | |
local ACCUMULATOR=0 | |
local SKIP=0 | |
local ENCODED="$1" | |
local REMAINING="$ENCODED" | |
local FEATURES="8 VERSION 1 24BIT_BASIC 1 24BIT_FULL 1 CLIPBOARD_WRITE 1 DECSLRM 1 MOUSE_BASIC 1 MOUSE_ALT_SCROLL 1 UTF8 1 DECSCUSR_BASIC 1 DECSCUSR_BAR 1 AMBIGUOUS_FULLWIDTH 4 UNICODE_VERSION 1 RTL_LEVEL1 1 RTL_LEVEL2 1 TITLE_SETTING 1 BRACKETED_PASTE 1 FOCUS_REPORTING 1 CWD 1 BCE 1 UNDERLINE_STYLING 1 UNDERLINE_STYLE_DOUBLE 1 UNDERLINE_STYLE_CURLY 1 UNDERLINE_STYLE_DOTTED 1 UNDERLINE_STYLE_DASHED 1 STRIKETHROUGH 1 OVERLINE 1 SYNC 1 HYPERLINKS 1 NOTIFICATIONS 1 SIXEL 1 ITALICS 1 INVERSE_7 0 EOF" | |
local BITS_NEEDED="${FEATURES%% *}"; FEATURES="${FEATURES#* }" | |
local FEATURE_NAME="${FEATURES%% *}"; FEATURES="${FEATURES#* }" | |
local VALUE=0 | |
while [ -n "$REMAINING" ]; do | |
# Read the next byte from the base64-encoded input. | |
local REST="${REMAINING#?}" | |
CHAR="${REMAINING%"$REST"}" | |
REMAINING="$REST" | |
if [ "$CHAR" = $'\n' ]; then | |
continue | |
fi | |
if [ "$CHAR" = '=' ]; then | |
ACCUMULATOR=$(( ACCUMULATOR << 6 )) | |
SKIP=$(( SKIP + 1 )) | |
continue | |
fi | |
# Look up the byte in our table, setting CHAR to its 1-based index. | |
CHAR=${TABLE#*$CHAR} | |
CHAR=$(( ${#TABLE}-${#CHAR} )) | |
if [ "$CHAR" = 0 ]; then | |
continue | |
fi | |
# Accrue six bits from CHAR into the accumulator. | |
ACCUMULATOR=$(( ACCUMULATOR << 6 | (CHAR - 1) )) | |
COUNT=$(( COUNT + 1 )) | |
if [ "$COUNT" -ne "4" ]; then | |
continue | |
fi | |
# We have decoded 24 bits of data. Process it. | |
LIMIT=$(( 8 * SKIP )) | |
local SHIFT=16 | |
while [ $SHIFT -ge $LIMIT ]; do | |
# Place the most significant unused byte from accumulator in CHAR. | |
CHAR=$(( ACCUMULATOR >> SHIFT & 255 )) | |
local BIT=0 | |
local UNSHIFT=0 | |
# Iterate over each bit in CHAR. | |
while [ $BIT -lt 8 ]; do | |
# OR the bit's value into VALUE. | |
local IS_SET=$(( (1 << BIT) & CHAR )) | |
VALUE=$(( VALUE + (IS_SET >> UNSHIFT) )) | |
BITS_NEEDED=$(( BITS_NEEDED - 1 )) | |
if [ $BITS_NEEDED = 0 ]; then | |
# We have read enough bits for the next feature. Output it. | |
export TF_"$FEATURE_NAME=$VALUE" | |
# Shift in the next feature. | |
BITS_NEEDED="${FEATURES%% *}"; FEATURES="${FEATURES#* }" | |
FEATURE_NAME="${FEATURES%% *}"; FEATURES="${FEATURES#* }" | |
VALUE=0 | |
UNSHIFT=$((BIT + 1)) | |
if [ $BITS_NEEDED = 0 ]; then | |
# 0 bits signals no more features are expected. | |
return | |
fi | |
fi | |
BIT=$(( BIT + 1 )) | |
done | |
SHIFT=$(( SHIFT - 8 )) | |
done | |
# Prepare to handle four more bytes of input. | |
ACCUMULATOR=0 | |
COUNT=0 | |
done | |
} | |
# Version 1. All features set to 1. | |
TEST1=$(echo -n 01FFFFFF FF03 | xxd -r -p - | base64) | |
__tf_decode $TEST1 | |
env | grep TF_ | |
# Version 255. All features set to 0. | |
TEST2=$(echo -n FF000000 0000 | xxd -r -p - | base64) | |
__tf_decode $TEST2 | |
env | grep TF_ | |
# Version 170, unicode=10, every other feature set to 1 | |
TEST3=$(echo -n AAAAAAAA AA02 | xxd -r -p - | base64) | |
__tf_decode $TEST3 | |
env | grep TF_ | |
# Version 85, unicode=5, every other feature set to 1 | |
TEST4=$(echo -n 55555555 5501 | xxd -r -p - | base64) | |
__tf_decode $TEST4 | |
env | grep TF_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment