Coverage for /var/devmt/py/utils4_1.8.0/utils4/convert.py: 100%

69 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2025-08-26 21:39 +0100

1#!/usr/bin/env python 

2# -*- coding: utf-8 -*- 

3""" 

4:Purpose: This module contains various low-level conversion functions. 

5 

6:Developer: J Berendt 

7:Email: development@s3dev.uk 

8 

9:Comments: Often, these types of conversions are called from a high-iteration 

10 loop. Therefore, the implementation of these functions has been 

11 written as close to core Python as possible, or in a C style, for 

12 efficiency purposes. 

13 

14""" 

15 

16# TODO: Move repeated messages into a central messaging class. 

17 

18def ascii2bin(asciistring: str) -> str: 

19 """Convert an ASCII string into a binary string representation. 

20 

21 Args: 

22 asciistring (str): ASCII string to be converted. 

23 

24 Returns: 

25 str: A binary string representation for the passed ASCII text, where 

26 each ASCII character is represented by an 8-bit binary string. 

27 

28 """ 

29 return ''.join(map(int2bin, ascii2int(asciistring))) 

30 

31def ascii2hex(asciistring: str) -> str: 

32 """Convert an ASCII string into a hexidecimal string. 

33 

34 Args: 

35 asciistring (str): ASCII string to be converted. 

36 

37 Returns: 

38 str: A hexidecimal string representation of the passed ASCII 

39 text. 

40 

41 """ 

42 return ''.join(map(int2hex, ascii2int(asciistring))) 

43 

44def ascii2int(asciistring: str) -> list: 

45 """Convert an ASCII string to a list of integers. 

46 

47 Args: 

48 asciistring (str): ASCII string to be converted. 

49 

50 Returns: 

51 list: A list of integers, as converted from he ASCII string. 

52 

53 """ 

54 return [ord(i) for i in asciistring] 

55 

56def bin2ascii(binstring: str, bits: int=8) -> str: 

57 """Convert a binary string representation into ASCII text. 

58 

59 Args: 

60 binstring (str): Binary string to be converted. 

61 bits (int, optional): Bit chunks into which the binary string is 

62 broken for conversion. Defaults to 8. 

63 

64 Returns: 

65 str: An ASCII string representation of the passed binary string. 

66 

67 """ 

68 if len(binstring) % bits: 

69 raise ValueError('The string length cannot be broken into ' 

70 f'{bits}-bit chunks.') 

71 ints = [] 

72 for chunk in range(0, len(binstring), bits): 

73 byte_ = binstring[chunk:chunk+bits] 

74 ints.append(bin2int(byte_, bits=bits)[0]) 

75 text = ''.join(map(int2ascii, ints)) 

76 return text 

77 

78def bin2int(binstring: str, bits: int=8) -> int: 

79 """Convert a binary string representation into an integer. 

80 

81 Args: 

82 binstring (str): Binary string to be converted. 

83 bits (int, optional): Bit chunks into which the binary string is 

84 broken for conversion. Defaults to 8. 

85 

86 Returns: 

87 int: Integer value from the binary string. 

88 

89 """ 

90 if len(binstring) % bits: 

91 raise ValueError('The string length cannot be broken into ' 

92 f'{bits}-bit chunks.') 

93 ints = [] 

94 for chunk in range(0, len(binstring), bits): 

95 int_ = 0 

96 s = 0 

97 byte = binstring[chunk:chunk+bits] 

98 for b in range(len(byte)-1, -1, -1): 

99 int_ += int(byte[b]) << s 

100 s += 1 

101 ints.append(int_) 

102 return ints 

103 

104def bin2hex(binstring: str, bits: int=8) -> str: 

105 """Convert a binary string representation into a hex string. 

106 

107 Args: 

108 binstring (str): Binary string to be converted. 

109 bits (int, optional): Bit chunks into which the binary string is 

110 broken for conversion. Defaults to 8. 

111 

112 Returns: 

113 A hexidecimal string representation of the passed binary string. 

114 

115 """ 

116 if len(binstring) % bits: 

117 raise ValueError('The string length cannot be broken into ' 

118 f'{bits}-bit chunks.') 

119 return ''.join(int2hex(i) for i in bin2int(binstring, bits=bits)) 

120 

121def hex2ascii(hexstring: str) -> str: 

122 """Convert a hexidecimal string to ASCII text. 

123 

124 Args: 

125 hexstring (str): Hex string to be converted. 

126 

127 Returns: 

128 str: An ASCII string representation for the passed hex string. 

129 

130 """ 

131 return ''.join(map(int2ascii, hex2int(hexstring))) 

132 

133def hex2bin(hexstring: str) -> str: 

134 """Convert a hexidecimal string into a binary string representation. 

135 

136 Args: 

137 hexstring (str): Hex string to be converted. 

138 

139 Returns: 

140 str: A binary string representation of the passed hex string. 

141 

142 """ 

143 return ''.join(map(int2bin, hex2int(hexstring))) 

144 

145def hex2int(hexstring: str, nbytes: int=1) -> int: 

146 """Convert a hexidecimal string to an integer. 

147 

148 Args: 

149 hexstring (str): Hex string to be converted. 

150 nbytes (int, optional): Number of bytes to consider for each 

151 decimal value. Defaults to 1. 

152 

153 :Examples: 

154 Example usage:: 

155 

156 hex2int(hexstring='c0ffee', nbytes=1) 

157 >>> [192, 255, 238] 

158 

159 hex2int(hexstring='c0ffee', nbytes=2) 

160 >>> [49407, 238] 

161 

162 hex2int(hexstring='c0ffee', nbytes=3) 

163 >>> [12648430] 

164 

165 Returns: 

166 list: A list of decimal values, as converted from the hex string. 

167 

168 """ 

169 # pylint: disable=multiple-statements 

170 nbytes *= 2 

171 out = [] 

172 # Split hex string into (n)-byte size chunks. 

173 for chunk in range(0, len(hexstring), nbytes): 

174 i = 0 

175 nib = 0 

176 for char in hexstring[chunk:nbytes+chunk]: 

177 if (char >= '0') & (char <= '9'): nib = ord(char) 

178 if (char >= 'a') & (char <= 'f'): nib = ord(char) + 9 

179 if (char >= 'A') & (char <= 'F'): nib = ord(char) + 9 

180 i = (i << 4) | (nib & 0xf) 

181 out.append(i) 

182 return out 

183 

184def int2ascii(i: int) -> str: 

185 """Convert an integer to an ASCII character. 

186 

187 Args: 

188 i (int): Integer value to be converted to ASCII text. 

189 

190 Note: 

191 The passed integer value must be <= 127. 

192 

193 Raises: 

194 ValueError: If the passed integer is > 127. 

195 

196 Returns: 

197 str: The ASCII character associated to the passed integer. 

198 

199 """ 

200 if i > 127: 

201 raise ValueError('The passed integer value must be <= 127.') 

202 return chr(i) 

203 

204def int2bin(i: int) -> str: 

205 """Convert an 8-bit integer to a binary string. 

206 

207 Args: 

208 i (int): Integer value to be converted. 

209 

210 Note: 

211 The passed integer value must be <= 255. 

212 

213 Raises: 

214 ValueError: If the passed integer is > 255. 

215 

216 Returns: 

217 str: A binary string representation of the passed integer. 

218 

219 """ 

220 if i > 255: # Limited to 1 byte. 

221 raise ValueError(f'Passed value exceeds 1 byte: i={i}') 

222 return ''.join(str((i >> shift) & 1) for shift in range(7, -1, -1)) 

223 

224def int2hex(i: int) -> str: 

225 """Convert an integer into a hexidecimal string. 

226 

227 Args: 

228 i (int): Integer value to be converted. 

229 

230 Returns: 

231 str: A two character hexidecimal string for the passed integer 

232 value. 

233 

234 """ 

235 chars = '0123456789abcdef' 

236 out = '' 

237 out_ = '' 

238 while i > 0: 

239 out_ += chars[i % 16] 

240 i //= 16 

241 # Output string must be reversed. 

242 for x in range(len(out_)-1, -1, -1): 

243 out += out_[x] 

244 # Pad so all hex values are two characters. 

245 if len(out) < 2: 

246 out = '0' + out 

247 return out