Source code for escape_mod
"""
Provides functions for escaping and unescaping strings.
It's not very space-efficient - it doubles the length of the string.
But it's pretty easy to read the quoted strings, and the code
is simple.
"""
import constants_mod
import helpers
[docs]def ordinal(char):
"""Convert a character to its ordinal value."""
if isinstance(char, int):
return char
int_list = helpers.string_to_binary(char)
assert len(int_list) == 1
byte_value = int_list[0]
assert 0 <= byte_value <= 255, "byte_value has a strange value: {}".format(byte_value)
return byte_value
[docs]def character(number):
"""Convert a single number from 0 to 255 to bytes."""
if 0 <= ordinal(number) <= 255:
return bytes([ordinal(number)])
else:
raise ValueError('Value %d not between 0 and 255 inclusive' % number)
[docs]def hexadecimal(hex_digit):
"""Convert a number from 0 to 15 to hexadecimal."""
if hex_digit >= 0 and hex_digit <= 15:
return '0123456789abcdef'[hex_digit]
else:
raise ValueError('Value %d not between 0 and 15 inclusive' % hex_digit)
[docs]def escape(string):
"""Escape a string for saving in a text format."""
# Note that it might be nice to have an encoding that's more human-readable, but getting urllib.request.quote past
# pylint was proving more trouble than it was worth
# sys.stderr.write('Escaping %s\n' % pathname)
special_set = set(constants_mod.Constants.b_special)
underscore = ordinal(constants_mod.Constants.b_underscore)
list_ = []
for one_char in string:
char = ordinal(one_char)
if ordinal(constants_mod.Constants.b_a) <= char <= ordinal(constants_mod.Constants.b_z):
list_.append(char)
list_.append(underscore)
elif ordinal(constants_mod.Constants.b_A) <= char <= ordinal(constants_mod.Constants.b_Z):
list_.append(char)
list_.append(underscore)
elif ordinal(constants_mod.Constants.b_0) <= char <= ordinal(constants_mod.Constants.b_9):
list_.append(char)
list_.append(underscore)
elif char in special_set:
list_.append(char)
list_.append(underscore)
else:
high_nybble = hexadecimal(char // 16)
low_nybble = hexadecimal(char & 15)
list_.append(ordinal(high_nybble))
list_.append(ordinal(low_nybble))
return bytes(list_)
[docs]def unescape(quoted_string):
"""Unescape an escaped string when retrieving from a text format."""
list_ = []
assert len(quoted_string) % 2 == 0
for position in range(0, len(quoted_string), 2):
if quoted_string[position + 1:position + 2] == constants_mod.Constants.b_underscore:
list_.append(quoted_string[position])
else:
one_byte = quoted_string[position:position + 2]
number = int(one_byte, 16)
list_.append(character(number))
ordinal_list = [ordinal(ch) for ch in list_]
return bytes(ordinal_list)