| # 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.') |