1# -*- coding: utf-8 -*- 2# 3# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# https://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Python compatibility wrappers.""" 18 19from __future__ import absolute_import 20 21import itertools 22import sys 23from struct import pack 24 25MAX_INT = sys.maxsize 26MAX_INT64 = (1 << 63) - 1 27MAX_INT32 = (1 << 31) - 1 28MAX_INT16 = (1 << 15) - 1 29 30PY2 = sys.version_info[0] == 2 31 32# Determine the word size of the processor. 33if MAX_INT == MAX_INT64: 34 # 64-bit processor. 35 MACHINE_WORD_SIZE = 64 36elif MAX_INT == MAX_INT32: 37 # 32-bit processor. 38 MACHINE_WORD_SIZE = 32 39else: 40 # Else we just assume 64-bit processor keeping up with modern times. 41 MACHINE_WORD_SIZE = 64 42 43if PY2: 44 integer_types = (int, long) 45 range = xrange 46 zip = itertools.izip 47else: 48 integer_types = (int, ) 49 range = range 50 zip = zip 51 52 53def write_to_stdout(data): 54 """Writes bytes to stdout 55 56 :type data: bytes 57 """ 58 if PY2: 59 sys.stdout.write(data) 60 else: 61 # On Py3 we must use the buffer interface to write bytes. 62 sys.stdout.buffer.write(data) 63 64 65def is_bytes(obj): 66 """ 67 Determines whether the given value is a byte string. 68 69 :param obj: 70 The value to test. 71 :returns: 72 ``True`` if ``value`` is a byte string; ``False`` otherwise. 73 """ 74 return isinstance(obj, bytes) 75 76 77def is_integer(obj): 78 """ 79 Determines whether the given value is an integer. 80 81 :param obj: 82 The value to test. 83 :returns: 84 ``True`` if ``value`` is an integer; ``False`` otherwise. 85 """ 86 return isinstance(obj, integer_types) 87 88 89def byte(num): 90 """ 91 Converts a number between 0 and 255 (both inclusive) to a base-256 (byte) 92 representation. 93 94 Use it as a replacement for ``chr`` where you are expecting a byte 95 because this will work on all current versions of Python:: 96 97 :param num: 98 An unsigned integer between 0 and 255 (both inclusive). 99 :returns: 100 A single byte. 101 """ 102 return pack("B", num) 103 104 105def xor_bytes(b1, b2): 106 """ 107 Returns the bitwise XOR result between two bytes objects, b1 ^ b2. 108 109 Bitwise XOR operation is commutative, so order of parameters doesn't 110 generate different results. If parameters have different length, extra 111 length of the largest one is ignored. 112 113 :param b1: 114 First bytes object. 115 :param b2: 116 Second bytes object. 117 :returns: 118 Bytes object, result of XOR operation. 119 """ 120 if PY2: 121 return ''.join(byte(ord(x) ^ ord(y)) for x, y in zip(b1, b2)) 122 123 return bytes(x ^ y for x, y in zip(b1, b2)) 124 125 126def get_word_alignment(num, force_arch=64, 127 _machine_word_size=MACHINE_WORD_SIZE): 128 """ 129 Returns alignment details for the given number based on the platform 130 Python is running on. 131 132 :param num: 133 Unsigned integral number. 134 :param force_arch: 135 If you don't want to use 64-bit unsigned chunks, set this to 136 anything other than 64. 32-bit chunks will be preferred then. 137 Default 64 will be used when on a 64-bit machine. 138 :param _machine_word_size: 139 (Internal) The machine word size used for alignment. 140 :returns: 141 4-tuple:: 142 143 (word_bits, word_bytes, 144 max_uint, packing_format_type) 145 """ 146 max_uint64 = 0xffffffffffffffff 147 max_uint32 = 0xffffffff 148 max_uint16 = 0xffff 149 max_uint8 = 0xff 150 151 if force_arch == 64 and _machine_word_size >= 64 and num > max_uint32: 152 # 64-bit unsigned integer. 153 return 64, 8, max_uint64, "Q" 154 elif num > max_uint16: 155 # 32-bit unsigned integer 156 return 32, 4, max_uint32, "L" 157 elif num > max_uint8: 158 # 16-bit unsigned integer. 159 return 16, 2, max_uint16, "H" 160 else: 161 # 8-bit unsigned integer. 162 return 8, 1, max_uint8, "B" 163