182 lines
3.9 KiB
Python
182 lines
3.9 KiB
Python
# Copyright 2014 Google Inc. All rights reserved.
|
|
#
|
|
# 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
|
|
#
|
|
# http://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.
|
|
|
|
import collections
|
|
import struct
|
|
|
|
from . import packer
|
|
from .compat import import_numpy, NumpyRequiredForThisFeature
|
|
|
|
np = import_numpy()
|
|
|
|
# For reference, see:
|
|
# https://docs.python.org/2/library/ctypes.html#ctypes-fundamental-data-types-2
|
|
|
|
# These classes could be collections.namedtuple instances, but those are new
|
|
# in 2.6 and we want to work towards 2.5 compatability.
|
|
|
|
class BoolFlags(object):
|
|
bytewidth = 1
|
|
min_val = False
|
|
max_val = True
|
|
py_type = bool
|
|
name = "bool"
|
|
packer_type = packer.boolean
|
|
|
|
|
|
class Uint8Flags(object):
|
|
bytewidth = 1
|
|
min_val = 0
|
|
max_val = (2**8) - 1
|
|
py_type = int
|
|
name = "uint8"
|
|
packer_type = packer.uint8
|
|
|
|
|
|
class Uint16Flags(object):
|
|
bytewidth = 2
|
|
min_val = 0
|
|
max_val = (2**16) - 1
|
|
py_type = int
|
|
name = "uint16"
|
|
packer_type = packer.uint16
|
|
|
|
|
|
class Uint32Flags(object):
|
|
bytewidth = 4
|
|
min_val = 0
|
|
max_val = (2**32) - 1
|
|
py_type = int
|
|
name = "uint32"
|
|
packer_type = packer.uint32
|
|
|
|
|
|
class Uint64Flags(object):
|
|
bytewidth = 8
|
|
min_val = 0
|
|
max_val = (2**64) - 1
|
|
py_type = int
|
|
name = "uint64"
|
|
packer_type = packer.uint64
|
|
|
|
|
|
class Int8Flags(object):
|
|
bytewidth = 1
|
|
min_val = -(2**7)
|
|
max_val = (2**7) - 1
|
|
py_type = int
|
|
name = "int8"
|
|
packer_type = packer.int8
|
|
|
|
|
|
class Int16Flags(object):
|
|
bytewidth = 2
|
|
min_val = -(2**15)
|
|
max_val = (2**15) - 1
|
|
py_type = int
|
|
name = "int16"
|
|
packer_type = packer.int16
|
|
|
|
|
|
class Int32Flags(object):
|
|
bytewidth = 4
|
|
min_val = -(2**31)
|
|
max_val = (2**31) - 1
|
|
py_type = int
|
|
name = "int32"
|
|
packer_type = packer.int32
|
|
|
|
|
|
class Int64Flags(object):
|
|
bytewidth = 8
|
|
min_val = -(2**63)
|
|
max_val = (2**63) - 1
|
|
py_type = int
|
|
name = "int64"
|
|
packer_type = packer.int64
|
|
|
|
|
|
class Float32Flags(object):
|
|
bytewidth = 4
|
|
min_val = None
|
|
max_val = None
|
|
py_type = float
|
|
name = "float32"
|
|
packer_type = packer.float32
|
|
|
|
|
|
class Float64Flags(object):
|
|
bytewidth = 8
|
|
min_val = None
|
|
max_val = None
|
|
py_type = float
|
|
name = "float64"
|
|
packer_type = packer.float64
|
|
|
|
|
|
class SOffsetTFlags(Int32Flags):
|
|
pass
|
|
|
|
|
|
class UOffsetTFlags(Uint32Flags):
|
|
pass
|
|
|
|
|
|
class VOffsetTFlags(Uint16Flags):
|
|
pass
|
|
|
|
|
|
def valid_number(n, flags):
|
|
if flags.min_val is None and flags.max_val is None:
|
|
return True
|
|
return flags.min_val <= n <= flags.max_val
|
|
|
|
|
|
def enforce_number(n, flags):
|
|
if flags.min_val is None and flags.max_val is None:
|
|
return
|
|
if not flags.min_val <= n <= flags.max_val:
|
|
raise TypeError("bad number %s for type %s" % (str(n), flags.name))
|
|
|
|
|
|
def float32_to_uint32(n):
|
|
packed = struct.pack("<1f", n)
|
|
(converted,) = struct.unpack("<1L", packed)
|
|
return converted
|
|
|
|
|
|
def uint32_to_float32(n):
|
|
packed = struct.pack("<1L", n)
|
|
(unpacked,) = struct.unpack("<1f", packed)
|
|
return unpacked
|
|
|
|
|
|
def float64_to_uint64(n):
|
|
packed = struct.pack("<1d", n)
|
|
(converted,) = struct.unpack("<1Q", packed)
|
|
return converted
|
|
|
|
|
|
def uint64_to_float64(n):
|
|
packed = struct.pack("<1Q", n)
|
|
(unpacked,) = struct.unpack("<1d", packed)
|
|
return unpacked
|
|
|
|
|
|
def to_numpy_type(number_type):
|
|
if np is not None:
|
|
return np.dtype(number_type.name).newbyteorder('<')
|
|
else:
|
|
raise NumpyRequiredForThisFeature('Numpy was not found.')
|