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 19 20 21# For reference, see: 22# https://docs.python.org/2/library/ctypes.html#ctypes-fundamental-data-types-2 23 24# These classes could be collections.namedtuple instances, but those are new 25# in 2.6 and we want to work towards 2.5 compatability. 26 27class BoolFlags(object): 28 bytewidth = 1 29 min_val = False 30 max_val = True 31 py_type = bool 32 name = "bool" 33 packer_type = packer.boolean 34 35 36class Uint8Flags(object): 37 bytewidth = 1 38 min_val = 0 39 max_val = (2**8) - 1 40 py_type = int 41 name = "uint8" 42 packer_type = packer.uint8 43 44 45class Uint16Flags(object): 46 bytewidth = 2 47 min_val = 0 48 max_val = (2**16) - 1 49 py_type = int 50 name = "uint16" 51 packer_type = packer.uint16 52 53 54class Uint32Flags(object): 55 bytewidth = 4 56 min_val = 0 57 max_val = (2**32) - 1 58 py_type = int 59 name = "uint32" 60 packer_type = packer.uint32 61 62 63class Uint64Flags(object): 64 bytewidth = 8 65 min_val = 0 66 max_val = (2**64) - 1 67 py_type = int 68 name = "uint64" 69 packer_type = packer.uint64 70 71 72class Int8Flags(object): 73 bytewidth = 1 74 min_val = -(2**7) 75 max_val = (2**7) - 1 76 py_type = int 77 name = "int8" 78 packer_type = packer.int8 79 80 81class Int16Flags(object): 82 bytewidth = 2 83 min_val = -(2**15) 84 max_val = (2**15) - 1 85 py_type = int 86 name = "int16" 87 packer_type = packer.int16 88 89 90class Int32Flags(object): 91 bytewidth = 4 92 min_val = -(2**31) 93 max_val = (2**31) - 1 94 py_type = int 95 name = "int32" 96 packer_type = packer.int32 97 98 99class Int64Flags(object): 100 bytewidth = 8 101 min_val = -(2**63) 102 max_val = (2**63) - 1 103 py_type = int 104 name = "int64" 105 packer_type = packer.int64 106 107 108class Float32Flags(object): 109 bytewidth = 4 110 min_val = None 111 max_val = None 112 py_type = float 113 name = "float32" 114 packer_type = packer.float32 115 116 117class Float64Flags(object): 118 bytewidth = 8 119 min_val = None 120 max_val = None 121 py_type = float 122 name = "float64" 123 packer_type = packer.float64 124 125 126class SOffsetTFlags(Int32Flags): 127 pass 128 129 130class UOffsetTFlags(Uint32Flags): 131 pass 132 133 134class VOffsetTFlags(Uint16Flags): 135 pass 136 137 138def valid_number(n, flags): 139 if flags.min_val is None and flags.max_val is None: 140 return True 141 return flags.min_val <= n <= flags.max_val 142 143 144def enforce_number(n, flags): 145 if flags.min_val is None and flags.max_val is None: 146 return 147 if not flags.min_val <= n <= flags.max_val: 148 raise TypeError("bad number %s for type %s" % (str(n), flags.name)) 149 150 151def float32_to_uint32(n): 152 packed = struct.pack("<1f", n) 153 (converted,) = struct.unpack("<1L", packed) 154 return converted 155 156 157def uint32_to_float32(n): 158 packed = struct.pack("<1L", n) 159 (unpacked,) = struct.unpack("<1f", packed) 160 return unpacked 161 162 163def float64_to_uint64(n): 164 packed = struct.pack("<1d", n) 165 (converted,) = struct.unpack("<1Q", packed) 166 return converted 167 168 169def uint64_to_float64(n): 170 packed = struct.pack("<1Q", n) 171 (unpacked,) = struct.unpack("<1d", packed) 172 return unpacked 173