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