Package dns :: Package rdtypes :: Package ANY :: Module LOC
[hide private]
[frames] | no frames]

Source Code for Module dns.rdtypes.ANY.LOC

  1  # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 
  2  # 
  3  # Permission to use, copy, modify, and distribute this software and its 
  4  # documentation for any purpose with or without fee is hereby granted, 
  5  # provided that the above copyright notice and this permission notice 
  6  # appear in all copies. 
  7  # 
  8  # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 
  9  # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 
 10  # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 
 11  # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
 12  # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
 13  # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 
 14  # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
 15   
 16  import struct 
 17   
 18  import dns.exception 
 19  import dns.rdata 
 20  from dns._compat import long, xrange 
 21   
 22   
 23  _pows = tuple(long(10**i) for i in range(0, 11)) 
 24   
 25  # default values are in centimeters 
 26  _default_size = 100.0 
 27  _default_hprec = 1000000.0 
 28  _default_vprec = 1000.0 
29 30 31 -def _exponent_of(what, desc):
32 if what == 0: 33 return 0 34 exp = None 35 for i in xrange(len(_pows)): 36 if what // _pows[i] == long(0): 37 exp = i - 1 38 break 39 if exp is None or exp < 0: 40 raise dns.exception.SyntaxError("%s value out of bounds" % desc) 41 return exp
42
43 44 -def _float_to_tuple(what):
45 if what < 0: 46 sign = -1 47 what *= -1 48 else: 49 sign = 1 50 what = long(round(what * 3600000)) 51 degrees = int(what // 3600000) 52 what -= degrees * 3600000 53 minutes = int(what // 60000) 54 what -= minutes * 60000 55 seconds = int(what // 1000) 56 what -= int(seconds * 1000) 57 what = int(what) 58 return (degrees, minutes, seconds, what, sign)
59
60 61 -def _tuple_to_float(what):
62 value = float(what[0]) 63 value += float(what[1]) / 60.0 64 value += float(what[2]) / 3600.0 65 value += float(what[3]) / 3600000.0 66 return float(what[4]) * value
67
68 69 -def _encode_size(what, desc):
70 what = long(what) 71 exponent = _exponent_of(what, desc) & 0xF 72 base = what // pow(10, exponent) & 0xF 73 return base * 16 + exponent
74
75 76 -def _decode_size(what, desc):
77 exponent = what & 0x0F 78 if exponent > 9: 79 raise dns.exception.SyntaxError("bad %s exponent" % desc) 80 base = (what & 0xF0) >> 4 81 if base > 9: 82 raise dns.exception.SyntaxError("bad %s base" % desc) 83 return long(base) * pow(10, exponent)
84
85 86 -class LOC(dns.rdata.Rdata):
87 88 """LOC record 89 90 @ivar latitude: latitude 91 @type latitude: (int, int, int, int, sign) tuple specifying the degrees, minutes, 92 seconds, milliseconds, and sign of the coordinate. 93 @ivar longitude: longitude 94 @type longitude: (int, int, int, int, sign) tuple specifying the degrees, 95 minutes, seconds, milliseconds, and sign of the coordinate. 96 @ivar altitude: altitude 97 @type altitude: float 98 @ivar size: size of the sphere 99 @type size: float 100 @ivar horizontal_precision: horizontal precision 101 @type horizontal_precision: float 102 @ivar vertical_precision: vertical precision 103 @type vertical_precision: float 104 @see: RFC 1876""" 105 106 __slots__ = ['latitude', 'longitude', 'altitude', 'size', 107 'horizontal_precision', 'vertical_precision'] 108
109 - def __init__(self, rdclass, rdtype, latitude, longitude, altitude, 110 size=_default_size, hprec=_default_hprec, 111 vprec=_default_vprec):
112 """Initialize a LOC record instance. 113 114 The parameters I{latitude} and I{longitude} may be either a 4-tuple 115 of integers specifying (degrees, minutes, seconds, milliseconds), 116 or they may be floating point values specifying the number of 117 degrees. The other parameters are floats. Size, horizontal precision, 118 and vertical precision are specified in centimeters.""" 119 120 super(LOC, self).__init__(rdclass, rdtype) 121 if isinstance(latitude, int) or isinstance(latitude, long): 122 latitude = float(latitude) 123 if isinstance(latitude, float): 124 latitude = _float_to_tuple(latitude) 125 self.latitude = latitude 126 if isinstance(longitude, int) or isinstance(longitude, long): 127 longitude = float(longitude) 128 if isinstance(longitude, float): 129 longitude = _float_to_tuple(longitude) 130 self.longitude = longitude 131 self.altitude = float(altitude) 132 self.size = float(size) 133 self.horizontal_precision = float(hprec) 134 self.vertical_precision = float(vprec)
135
136 - def to_text(self, origin=None, relativize=True, **kw):
137 if self.latitude[4] > 0: 138 lat_hemisphere = 'N' 139 lat_degrees = self.latitude[0] 140 else: 141 lat_hemisphere = 'S' 142 lat_degrees = -1 * self.latitude[0] 143 if self.longitude[4] > 0: 144 long_hemisphere = 'E' 145 long_degrees = self.longitude[0] 146 else: 147 long_hemisphere = 'W' 148 long_degrees = -1 * self.longitude[0] 149 text = "%d %d %d.%03d %s %d %d %d.%03d %s %0.2fm" % ( 150 self.latitude[0], self.latitude[1], 151 self.latitude[2], self.latitude[3], lat_hemisphere, 152 self.longitude[0], self.longitude[1], self.longitude[2], 153 self.longitude[3], long_hemisphere, 154 self.altitude / 100.0 155 ) 156 157 # do not print default values 158 if self.size != _default_size or \ 159 self.horizontal_precision != _default_hprec or \ 160 self.vertical_precision != _default_vprec: 161 text += " %0.2fm %0.2fm %0.2fm" % ( 162 self.size / 100.0, self.horizontal_precision / 100.0, 163 self.vertical_precision / 100.0 164 ) 165 return text
166 167 @classmethod
168 - def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
169 latitude = [0, 0, 0, 0, 1] 170 longitude = [0, 0, 0, 0, 1] 171 size = _default_size 172 hprec = _default_hprec 173 vprec = _default_vprec 174 175 latitude[0] = tok.get_int() 176 t = tok.get_string() 177 if t.isdigit(): 178 latitude[1] = int(t) 179 t = tok.get_string() 180 if '.' in t: 181 (seconds, milliseconds) = t.split('.') 182 if not seconds.isdigit(): 183 raise dns.exception.SyntaxError( 184 'bad latitude seconds value') 185 latitude[2] = int(seconds) 186 if latitude[2] >= 60: 187 raise dns.exception.SyntaxError('latitude seconds >= 60') 188 l = len(milliseconds) 189 if l == 0 or l > 3 or not milliseconds.isdigit(): 190 raise dns.exception.SyntaxError( 191 'bad latitude milliseconds value') 192 if l == 1: 193 m = 100 194 elif l == 2: 195 m = 10 196 else: 197 m = 1 198 latitude[3] = m * int(milliseconds) 199 t = tok.get_string() 200 elif t.isdigit(): 201 latitude[2] = int(t) 202 t = tok.get_string() 203 if t == 'S': 204 latitude[4] = -1 205 elif t != 'N': 206 raise dns.exception.SyntaxError('bad latitude hemisphere value') 207 208 longitude[0] = tok.get_int() 209 t = tok.get_string() 210 if t.isdigit(): 211 longitude[1] = int(t) 212 t = tok.get_string() 213 if '.' in t: 214 (seconds, milliseconds) = t.split('.') 215 if not seconds.isdigit(): 216 raise dns.exception.SyntaxError( 217 'bad longitude seconds value') 218 longitude[2] = int(seconds) 219 if longitude[2] >= 60: 220 raise dns.exception.SyntaxError('longitude seconds >= 60') 221 l = len(milliseconds) 222 if l == 0 or l > 3 or not milliseconds.isdigit(): 223 raise dns.exception.SyntaxError( 224 'bad longitude milliseconds value') 225 if l == 1: 226 m = 100 227 elif l == 2: 228 m = 10 229 else: 230 m = 1 231 longitude[3] = m * int(milliseconds) 232 t = tok.get_string() 233 elif t.isdigit(): 234 longitude[2] = int(t) 235 t = tok.get_string() 236 if t == 'W': 237 longitude[4] = -1 238 elif t != 'E': 239 raise dns.exception.SyntaxError('bad longitude hemisphere value') 240 241 t = tok.get_string() 242 if t[-1] == 'm': 243 t = t[0: -1] 244 altitude = float(t) * 100.0 # m -> cm 245 246 token = tok.get().unescape() 247 if not token.is_eol_or_eof(): 248 value = token.value 249 if value[-1] == 'm': 250 value = value[0: -1] 251 size = float(value) * 100.0 # m -> cm 252 token = tok.get().unescape() 253 if not token.is_eol_or_eof(): 254 value = token.value 255 if value[-1] == 'm': 256 value = value[0: -1] 257 hprec = float(value) * 100.0 # m -> cm 258 token = tok.get().unescape() 259 if not token.is_eol_or_eof(): 260 value = token.value 261 if value[-1] == 'm': 262 value = value[0: -1] 263 vprec = float(value) * 100.0 # m -> cm 264 tok.get_eol() 265 266 return cls(rdclass, rdtype, latitude, longitude, altitude, 267 size, hprec, vprec)
268
269 - def to_wire(self, file, compress=None, origin=None):
270 milliseconds = (self.latitude[0] * 3600000 + 271 self.latitude[1] * 60000 + 272 self.latitude[2] * 1000 + 273 self.latitude[3]) * self.latitude[4] 274 latitude = long(0x80000000) + milliseconds 275 milliseconds = (self.longitude[0] * 3600000 + 276 self.longitude[1] * 60000 + 277 self.longitude[2] * 1000 + 278 self.longitude[3]) * self.longitude[4] 279 longitude = long(0x80000000) + milliseconds 280 altitude = long(self.altitude) + long(10000000) 281 size = _encode_size(self.size, "size") 282 hprec = _encode_size(self.horizontal_precision, "horizontal precision") 283 vprec = _encode_size(self.vertical_precision, "vertical precision") 284 wire = struct.pack("!BBBBIII", 0, size, hprec, vprec, latitude, 285 longitude, altitude) 286 file.write(wire)
287 288 @classmethod
289 - def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
290 (version, size, hprec, vprec, latitude, longitude, altitude) = \ 291 struct.unpack("!BBBBIII", wire[current: current + rdlen]) 292 if latitude > long(0x80000000): 293 latitude = float(latitude - long(0x80000000)) / 3600000 294 else: 295 latitude = -1 * float(long(0x80000000) - latitude) / 3600000 296 if latitude < -90.0 or latitude > 90.0: 297 raise dns.exception.FormError("bad latitude") 298 if longitude > long(0x80000000): 299 longitude = float(longitude - long(0x80000000)) / 3600000 300 else: 301 longitude = -1 * float(long(0x80000000) - longitude) / 3600000 302 if longitude < -180.0 or longitude > 180.0: 303 raise dns.exception.FormError("bad longitude") 304 altitude = float(altitude) - 10000000.0 305 size = _decode_size(size, "size") 306 hprec = _decode_size(hprec, "horizontal precision") 307 vprec = _decode_size(vprec, "vertical precision") 308 return cls(rdclass, rdtype, latitude, longitude, altitude, 309 size, hprec, vprec)
310
311 - def _get_float_latitude(self):
312 return _tuple_to_float(self.latitude)
313
314 - def _set_float_latitude(self, value):
316 317 float_latitude = property(_get_float_latitude, _set_float_latitude, 318 doc="latitude as a floating point value") 319
320 - def _get_float_longitude(self):
321 return _tuple_to_float(self.longitude)
322
323 - def _set_float_longitude(self, value):
325 326 float_longitude = property(_get_float_longitude, _set_float_longitude, 327 doc="longitude as a floating point value")
328