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

Source Code for Module dns.rdtypes.ANY.LOC

  1  # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 
  2   
  3  # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 
  4  # 
  5  # Permission to use, copy, modify, and distribute this software and its 
  6  # documentation for any purpose with or without fee is hereby granted, 
  7  # provided that the above copyright notice and this permission notice 
  8  # appear in all copies. 
  9  # 
 10  # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 
 11  # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 
 12  # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 
 13  # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
 14  # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
 15  # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 
 16  # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
 17   
 18  from __future__ import division 
 19   
 20  import struct 
 21   
 22  import dns.exception 
 23  import dns.rdata 
 24  from dns._compat import long, xrange, round_py2_compat 
 25   
 26   
 27  _pows = tuple(long(10**i) for i in range(0, 11)) 
 28   
 29  # default values are in centimeters 
 30  _default_size = 100.0 
 31  _default_hprec = 1000000.0 
 32  _default_vprec = 1000.0 
33 34 35 -def _exponent_of(what, desc):
36 if what == 0: 37 return 0 38 exp = None 39 for i in xrange(len(_pows)): 40 if what // _pows[i] == long(0): 41 exp = i - 1 42 break 43 if exp is None or exp < 0: 44 raise dns.exception.SyntaxError("%s value out of bounds" % desc) 45 return exp
46
47 48 -def _float_to_tuple(what):
49 if what < 0: 50 sign = -1 51 what *= -1 52 else: 53 sign = 1 54 what = round_py2_compat(what * 3600000) 55 degrees = int(what // 3600000) 56 what -= degrees * 3600000 57 minutes = int(what // 60000) 58 what -= minutes * 60000 59 seconds = int(what // 1000) 60 what -= int(seconds * 1000) 61 what = int(what) 62 return (degrees, minutes, seconds, what, sign)
63
64 65 -def _tuple_to_float(what):
66 value = float(what[0]) 67 value += float(what[1]) / 60.0 68 value += float(what[2]) / 3600.0 69 value += float(what[3]) / 3600000.0 70 return float(what[4]) * value
71
72 73 -def _encode_size(what, desc):
74 what = long(what) 75 exponent = _exponent_of(what, desc) & 0xF 76 base = what // pow(10, exponent) & 0xF 77 return base * 16 + exponent
78
79 80 -def _decode_size(what, desc):
81 exponent = what & 0x0F 82 if exponent > 9: 83 raise dns.exception.SyntaxError("bad %s exponent" % desc) 84 base = (what & 0xF0) >> 4 85 if base > 9: 86 raise dns.exception.SyntaxError("bad %s base" % desc) 87 return long(base) * pow(10, exponent)
88
89 90 -class LOC(dns.rdata.Rdata):
91 92 """LOC record 93 94 @ivar latitude: latitude 95 @type latitude: (int, int, int, int, sign) tuple specifying the degrees, minutes, 96 seconds, milliseconds, and sign of the coordinate. 97 @ivar longitude: longitude 98 @type longitude: (int, int, int, int, sign) tuple specifying the degrees, 99 minutes, seconds, milliseconds, and sign of the coordinate. 100 @ivar altitude: altitude 101 @type altitude: float 102 @ivar size: size of the sphere 103 @type size: float 104 @ivar horizontal_precision: horizontal precision 105 @type horizontal_precision: float 106 @ivar vertical_precision: vertical precision 107 @type vertical_precision: float 108 @see: RFC 1876""" 109 110 __slots__ = ['latitude', 'longitude', 'altitude', 'size', 111 'horizontal_precision', 'vertical_precision'] 112
113 - def __init__(self, rdclass, rdtype, latitude, longitude, altitude, 114 size=_default_size, hprec=_default_hprec, 115 vprec=_default_vprec):
116 """Initialize a LOC record instance. 117 118 The parameters I{latitude} and I{longitude} may be either a 4-tuple 119 of integers specifying (degrees, minutes, seconds, milliseconds), 120 or they may be floating point values specifying the number of 121 degrees. The other parameters are floats. Size, horizontal precision, 122 and vertical precision are specified in centimeters.""" 123 124 super(LOC, self).__init__(rdclass, rdtype) 125 if isinstance(latitude, int) or isinstance(latitude, long): 126 latitude = float(latitude) 127 if isinstance(latitude, float): 128 latitude = _float_to_tuple(latitude) 129 self.latitude = latitude 130 if isinstance(longitude, int) or isinstance(longitude, long): 131 longitude = float(longitude) 132 if isinstance(longitude, float): 133 longitude = _float_to_tuple(longitude) 134 self.longitude = longitude 135 self.altitude = float(altitude) 136 self.size = float(size) 137 self.horizontal_precision = float(hprec) 138 self.vertical_precision = float(vprec)
139
140 - def to_text(self, origin=None, relativize=True, **kw):
141 if self.latitude[4] > 0: 142 lat_hemisphere = 'N' 143 else: 144 lat_hemisphere = 'S' 145 if self.longitude[4] > 0: 146 long_hemisphere = 'E' 147 else: 148 long_hemisphere = 'W' 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.2f}m {:0.2f}m {:0.2f}m".format( 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