1# Copyright 2014 Google Inc. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import collections 16import struct 17 18from . import packer 19from .compat import import_numpy, NumpyRequiredForThisFeature 20 21np = import_numpy() 22 23# For reference, see: 24# https://docs.python.org/2/library/ctypes.html#ctypes-fundamental-data-types-2 25 26# These classes could be collections.namedtuple instances, but those are new 27# in 2.6 and we want to work towards 2.5 compatability. 28 29class BoolFlags(object): 30 bytewidth = 1 31 min_val = False 32 max_val = True 33 py_type = bool 34 name = "bool" 35 packer_type = packer.boolean 36 37 38class Uint8Flags(object): 39 bytewidth = 1 40 min_val = 0 41 max_val = (2**8) - 1 42 py_type = int 43 name = "uint8" 44 packer_type = packer.uint8 45 46 47class Uint16Flags(object): 48 bytewidth = 2 49 min_val = 0 50 max_val = (2**16) - 1 51 py_type = int 52 name = "uint16" 53 packer_type = packer.uint16 54 55 56class Uint32Flags(object): 57 bytewidth = 4 58 min_val = 0 59 max_val = (2**32) - 1 60 py_type = int 61 name = "uint32" 62 packer_type = packer.uint32 63 64 65class Uint64Flags(object): 66 bytewidth = 8 67 min_val = 0 68 max_val = (2**64) - 1 69 py_type = int 70 name = "uint64" 71 packer_type = packer.uint64 72 73 74class Int8Flags(object): 75 bytewidth = 1 76 min_val = -(2**7) 77 max_val = (2**7) - 1 78 py_type = int 79 name = "int8" 80 packer_type = packer.int8 81 82 83class Int16Flags(object): 84 bytewidth = 2 85 min_val = -(2**15) 86 max_val = (2**15) - 1 87 py_type = int 88 name = "int16" 89 packer_type = packer.int16 90 91 92class Int32Flags(object): 93 bytewidth = 4 94 min_val = -(2**31) 95 max_val = (2**31) - 1 96 py_type = int 97 name = "int32" 98 packer_type = packer.int32 99 100 101class Int64Flags(object): 102 bytewidth = 8 103 min_val = -(2**63) 104 max_val = (2**63) - 1 105 py_type = int 106 name = "int64" 107 packer_type = packer.int64 108 109 110class Float32Flags(object): 111 bytewidth = 4 112 min_val = None 113 max_val = None 114 py_type = float 115 name = "float32" 116 packer_type = packer.float32 117 118 119class Float64Flags(object): 120 bytewidth = 8 121 min_val = None 122 max_val = None 123 py_type = float 124 name = "float64" 125 packer_type = packer.float64 126 127 128class SOffsetTFlags(Int32Flags): 129 pass 130 131 132class UOffsetTFlags(Uint32Flags): 133 pass 134 135 136class VOffsetTFlags(Uint16Flags): 137 pass 138 139 140def valid_number(n, flags): 141 if flags.min_val is None and flags.max_val is None: 142 return True 143 return flags.min_val <= n <= flags.max_val 144 145 146def enforce_number(n, flags): 147 if flags.min_val is None and flags.max_val is None: 148 return 149 if not flags.min_val <= n <= flags.max_val: 150 raise TypeError("bad number %s for type %s" % (str(n), flags.name)) 151 152 153def float32_to_uint32(n): 154 packed = struct.pack("<1f", n) 155 (converted,) = struct.unpack("<1L", packed) 156 return converted 157 158 159def uint32_to_float32(n): 160 packed = struct.pack("<1L", n) 161 (unpacked,) = struct.unpack("<1f", packed) 162 return unpacked 163 164 165def float64_to_uint64(n): 166 packed = struct.pack("<1d", n) 167 (converted,) = struct.unpack("<1Q", packed) 168 return converted 169 170 171def uint64_to_float64(n): 172 packed = struct.pack("<1Q", n) 173 (unpacked,) = struct.unpack("<1d", packed) 174 return unpacked 175 176 177def to_numpy_type(number_type): 178 if np is not None: 179 return np.dtype(number_type.name).newbyteorder('<') 180 else: 181 raise NumpyRequiredForThisFeature('Numpy was not found.') 182