• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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#      http://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
19
20from __future__ import absolute_import
21
22import sys
23from struct import pack
24
25try:
26    MAX_INT = sys.maxsize
27except AttributeError:
28    MAX_INT = sys.maxint
29
30MAX_INT64 = (1 << 63) - 1
31MAX_INT32 = (1 << 31) - 1
32MAX_INT16 = (1 << 15) - 1
33
34# Determine the word size of the processor.
35if MAX_INT == MAX_INT64:
36    # 64-bit processor.
37    MACHINE_WORD_SIZE = 64
38elif MAX_INT == MAX_INT32:
39    # 32-bit processor.
40    MACHINE_WORD_SIZE = 32
41else:
42    # Else we just assume 64-bit processor keeping up with modern times.
43    MACHINE_WORD_SIZE = 64
44
45
46try:
47    # < Python3
48    unicode_type = unicode
49    have_python3 = False
50except NameError:
51    # Python3.
52    unicode_type = str
53    have_python3 = True
54
55# Fake byte literals.
56if str is unicode_type:
57    def byte_literal(s):
58        return s.encode('latin1')
59else:
60    def byte_literal(s):
61        return s
62
63# ``long`` is no more. Do type detection using this instead.
64try:
65    integer_types = (int, long)
66except NameError:
67    integer_types = (int,)
68
69b = byte_literal
70
71try:
72    # Python 2.6 or higher.
73    bytes_type = bytes
74except NameError:
75    # Python 2.5
76    bytes_type = str
77
78
79# To avoid calling b() multiple times in tight loops.
80ZERO_BYTE = b('\x00')
81EMPTY_BYTE = b('')
82
83
84def is_bytes(obj):
85    """
86    Determines whether the given value is a byte string.
87
88    :param obj:
89        The value to test.
90    :returns:
91        ``True`` if ``value`` is a byte string; ``False`` otherwise.
92    """
93    return isinstance(obj, bytes_type)
94
95
96def is_integer(obj):
97    """
98    Determines whether the given value is an integer.
99
100    :param obj:
101        The value to test.
102    :returns:
103        ``True`` if ``value`` is an integer; ``False`` otherwise.
104    """
105    return isinstance(obj, integer_types)
106
107
108def byte(num):
109    """
110    Converts a number between 0 and 255 (both inclusive) to a base-256 (byte)
111    representation.
112
113    Use it as a replacement for ``chr`` where you are expecting a byte
114    because this will work on all current versions of Python::
115
116    :param num:
117        An unsigned integer between 0 and 255 (both inclusive).
118    :returns:
119        A single byte.
120    """
121    return pack("B", num)
122
123
124def get_word_alignment(num, force_arch=64,
125                       _machine_word_size=MACHINE_WORD_SIZE):
126    """
127    Returns alignment details for the given number based on the platform
128    Python is running on.
129
130    :param num:
131        Unsigned integral number.
132    :param force_arch:
133        If you don't want to use 64-bit unsigned chunks, set this to
134        anything other than 64. 32-bit chunks will be preferred then.
135        Default 64 will be used when on a 64-bit machine.
136    :param _machine_word_size:
137        (Internal) The machine word size used for alignment.
138    :returns:
139        4-tuple::
140
141            (word_bits, word_bytes,
142             max_uint, packing_format_type)
143    """
144    max_uint64 = 0xffffffffffffffff
145    max_uint32 = 0xffffffff
146    max_uint16 = 0xffff
147    max_uint8 = 0xff
148
149    if force_arch == 64 and _machine_word_size >= 64 and num > max_uint32:
150        # 64-bit unsigned integer.
151        return 64, 8, max_uint64, "Q"
152    elif num > max_uint16:
153        # 32-bit unsigned integer
154        return 32, 4, max_uint32, "L"
155    elif num > max_uint8:
156        # 16-bit unsigned integer.
157        return 16, 2, max_uint16, "H"
158    else:
159        # 8-bit unsigned integer.
160        return 8, 1, max_uint8, "B"
161